3916: [Baltic2014]friends
Time Limit: 30 Sec Memory Limit: 256 MB
Submit: 1082 Solved: 357
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
解析:
枚举改变的位置的前一个位置,用字符串哈希判断即可。
代码:
#include <bits/stdc++.h>
#include <tr1/unordered_map>
using namespace std;
using namespace std::tr1;
const int Max=2000005;
int n,m,sum,len,pos;
int inv[132];
unsigned long long Pow[Max],Hash[Max];
char ch[Max];
unordered_map<long long,bool>v;
inline void pre()
{
Pow[0]=1;
for(int i=1;i<=n;i++)
{
Hash[i] = Hash[i-1] * 131 + (ch[i] - 'A' + 1);
Pow[i] = Pow[i-1] * 131;
}
}
inline unsigned long long calc1(unsigned long long m)
{
return Hash[m] * Pow[len-m] + Hash[len+1] - Hash[m+1] * Pow[len-m];
}
inline unsigned long long calc2(unsigned long long m)
{
return (Hash[m] - Hash[len] * Pow[m-len]) * Pow[n-m-1] + Hash[n] - Hash[m+1] * Pow[n-m-1];
}
int main()
{
scanf("%d\n%s",&n,ch+1);
if(!(n&1)) {cout<<"NOT POSSIBLE\n";return 0;}
pre();
len=(n-1)>>1;
for(int i=0;i<n;i++)
{
unsigned long long a=0,b=0;
if(i<len)
{
a=calc1(i);
b=Hash[n] - Hash[n-len] * Pow[len];
}
else
{
a=Hash[len];
b=calc2(i);
}
if(a==b && !v[a]) v[a]=1,sum++,pos=i+1;
}
if(!sum) {cout<<"NOT POSSIBLE\n";return 0;}
int x=0;
if(sum==1)
{
for(int i=1;i<=n;i++)
{
if(i!=pos)
{
cout<<ch[i];
x++;
}
if(x==len) break;
}
}
else cout<<"NOT UNIQUE\n";
return 0;
}
代码: