题目地址:https://www.lydsy.com/JudgeOnline/problem.php?id=3916
题目:
Description
有三个好朋友喜欢在一起玩游戏,A君写下一个字符串S,B君将其复制一遍得到T,C君在T的任意位置(包括首尾)插入一个字符得到U.现在你得到了U,请你找出S.
Input
第一行一个数N,表示U的长度.
第二行一个字符串U,保证U由大写字母组成
Output
输出一行,若S不存在,输出"NOT POSSIBLE".若S不唯一,输出"NOT UNIQUE".否则输出S.
Sample Input
Sample Input1:
7
ABXCABC
Sample Input2:
6
ABCDEF
Sample Input3:
9
ABABABABA
Sample Output
Sample Output1:
ABC
Sample Output2:
NOT POSSIBLE
Sample Output3:
NOT UNIQUE
HINT
对于100%的数据 2<=N<=2000001
解题思路:
n为偶数:NOT POSSIBLE,因为按照题意,n应该为奇数。
令half = n / 2,讨论插入的字母在左侧,中间,右侧三种情况,每次判断两个子串(或子序列)的hash值是否相同,不统计相同的S。
例如:字符串aaabaab
i | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
s[i] | a | a | a | b | a | a | b |
遍历i, 插入的字母在i位置上。当i=1时,两个串s1="aab" s2="aab' 相同,所以可知S="aab", 当i=2时,s1="aab",s2="aab",s1=s2,S'="aab",S'=S,所以重复统计,这种情况不算NOT UNIQUE。
如何求s[1]s[2]s[4]s[5]这四个字母组成的字符串的hash值呢?
其实字符串hash相当于把字符串映射成一个p进制的数。
s[1]s[2]组成的hash值=hash[2], s[4]s[5]组成的hash值= hash[5] - hash[3] *
所以s[1]s[2]s[4]s[5]对应的hash值= hash[2] * + hash[5] - hash[3] *
把表格里的a,b换成1,2,映射成10进制的数想一想就懂啦?️下标不要写错!
ac代码:
并没有题目给的30s那么吓人?
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const ll maxn = 2000010;
const ll p = 2333323;
ll has[maxn], power[maxn];
char s[maxn];
int main()
{
//freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);
int n;
scanf("%d", &n);
scanf("%s", s + 1);
if(n % 2 == 0)
{
printf("NOT POSSIBLE\n");
return 0;
}
has[0] = 0, power[0] = 1;
for(int i = 1; i <= n; i++)
{
power[i] = power[i - 1] * p;
has[i] = has[i - 1] * p + (ll)(s[i] - 'A' + 1);
}
int half = n / 2, pos = 0;
ll ans = 0;
for(int i = 1; i <= n; i++)
{
if(i <= half)
{
ll l = has[i - 1] * power[half + 1 - i] + has[half + 1] - has[i] * power[half + 1 - i];
ll r = has[n] - has[half + 1] * power[half];
if(l == r)
{
pos = i;
if(!ans) ans = l;
}
}
else if(i == half +1)
{
ll l = has[half];
ll r = has[n] - has[half + 1] * power[half];
if(l == r)
{
pos = i;
if(!ans) ans = l;
else if(ans != l)
{
printf("NOT UNIQUE\n");
return 0;
}
}
}
else // i > half + 1
{
ll l = has[half];
ll r = (has[i - 1] - has[half] * power[i - half -1]) * power[n - i] + has[n] - has[i] * power[n - i];
if(l == r)
{
pos = i;
if(!ans) ans = l;
else if(ans != l)
{
printf("NOT UNIQUE\n");
return 0;
}
}
}
}
if(ans == 0) printf("NOT POSSIBLE\n");
else
{
if(pos <= half + 1) //输出右侧
printf("%s\n",s + half + 2);
else
{
for(int i = 1; i <= half; i++) //输出左侧
printf("%c",s[i]);
}
}
return 0;
}