friends #2823. 「BalticOI 2014 Day 1」三个朋友
作者:互联网
[BalticOI 2014 Day1] Three Friends
题目描述
有一个字符串 \(S\),对他进行操作:
- 将 \(S\) 复制为两份,存在字符串 \(T\) 中
- 在 \(T\) 的某一位置上插入一个字符,得到字符串 \(U\)
现在给定 \(U\),求 \(S\)。
输入格式
第一行一个整数 \(N\) 代表 \(U\) 的长度。
第二行 \(N\) 个字符代表字符串 \(U\)。
输出格式
- 如果不能通过上述的步骤从 \(S\) 推到 \(U\),输出
NOT POSSIBLE
。 - 如果从 \(U\) 得到的 \(S\) 不是唯一的,输出
NOT UNIQUE
。 - 否则,输出一个字符串 \(S\)。
样例 #1
样例输入 #1
7
ABXCABC
样例输出 #1
ABC
样例 #2
样例输入 #2
6
ABCDEF
样例输出 #2
NOT POSSIBLE
样例 #3
样例输入 #3
9
ABABABABA
样例输出 #3
NOT UNIQUE
提示
数据规模与约定
本题采用捆绑测试。
- Subtask 1(35 pts):\(N \le 2001\)。
- Subtask 2(65 pts):无特殊限制。
对于 \(100\%\) 的数据,\(2 \le N \le 2 \times 10^6+1\),保证 \(U\) 中只包含大写字母。
说明
翻译自 BalticOI 2014 Day1 B Three Friends。
思路
这题是一体经典的字符串哈希题,我们可以先求出每个字符串得哈希值,但是这题有些字符串有多余字符,因为每一个哈希值都是\(p\)进制数,所以我们可以通过进制转换来消除多余得字符。比如\(abcde\)这么一个字符串有\(c\)这个字符是多余得,那该怎么得到\(abde\)这么一个字符串呢?我们可以先把原字符串以\(c\)分割成\(ab\)和\(de\),因为除去\(c\)后面的字符串长度为\(2\),所以答案就是\(ab\times p^2+cd=abcd\)
代码
#include <iostream>
using namespace std;
typedef unsigned long long ULL;
const int N = 2000010,BASE = 131;
int n;
char s[N];
ULL h[N],p[N];
void string_hash_prework () {
p[0] = 1;
for (int i = 1;i <= n;i++) {
h[i] = h[i-1] * BASE + (s[i] - 'A' + 1);
p[i] = p[i-1] * BASE;
}
}
ULL query (int l,int r) {
return h[r]-h[l-1]*p[r-l+1];
}
int main () {
scanf ("%d%s",&n,s+1);
if ((n & 1) == 0) printf ("NOT POSSIBLE");
else {
string_hash_prework ();
int t = 0;
ULL ans = 0;
bool flag = false;
for (int i = 1;i <= n;i++) {
ULL h1,h2;
if (i <= n/2) h1 = query (1,i-1)*p[n/2-i+1]+query (i+1,n/2+1);
else h1 = query (1,n/2);
if (i <= n/2+1) h2 = query (n/2+2,n);
else h2 = query (n/2+1,i-1)*p[n-i]+query (i+1,n);
if (h1 == h2) {
if (flag && ans != h1) {
printf ("NOT UNIQUE");
return 0;
}
flag = true;
ans = h1,t = i;
}
}
if (!flag) printf ("NOT POSSIBLE");
else {
int cnt = 1;
for (int i = 1;cnt <= n/2;i++) {
if (i != t) {
printf ("%c",s[i]);
cnt++;
}
}
}
printf ("\n");
}
return 0;
}
标签:输出,le,样例,哈希,BalticOI,字符串,2014,friends 来源: https://www.cnblogs.com/incra/p/16454159.html