白嫖怪Long Long
问题描述
Long Long准备去吃串串,刚好发现串串店正在搞活动,只要能帮店主解决一个问题,这一顿就可以白嫖。作为白嫖怪,Long Long怎么能错过这次机会,但是他是一个字符串渣渣,现在需要你来帮他解决。由于他十分着急吃串串,他只给你1s的时间解决这个问题。
问题是这样的:店主十分喜欢回文串(正着读和反着读都一样的字符串),比如 “nucun”,“acmmca” 这样的都是回文串,现在店主随机给你出两个字符串a和b,如果b串是回文串,求出a串中b串出现的个数和出现的所有位置。要求你写一个程序可以解决所有这样的问题。
输入描述
第一行输入一个t,表示有t(1<=t<=10)组样例。
接下来有t组,每组输入两个字符串a和b,1<=|a|<=1000000, 1<=|b|<=1000000。
输出描述
对于每个样例,如果b串不是回文串输出一行"NO",否则输出一行"YES",并输出一个数m,表示b串在a串中出现了几次,接下来输出m行,按起始位置的字典序由小到大输出b串在a串出现的起始位置和终点位置。每个样例之间有一个空行。
样例输入
3
abbbabbbabbb
a
abba
abc
aaaa
aa
样例输出
YES
3
1 1
5 5
9 9
NO
YES
3
1 2
2 3
3 4
#include<iostream>
#include<algorithm>
#include<set>
#include<vector>
#include<map>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
using namespace std;
const int N = 1e6+10;
int a[N];
int ne[N];
char p[N];
char s[N];
int n, m;
void init()
{
for(int i=2, j=0; i<=m; i++)
{
while(j && p[i] != p[j+1])
{
j = ne[j];
}
if(p[i] == p[j+1])
j++;
ne[i] = j;
}
for(int i=n; i>=1; i--)
{
s[i] = s[i-1];
}
for(int i=m; i>=1; i--)
{
p[i] = p[i-1];
}
}
bool fan(int l)
{
int res = l / 2;
for(int i=1; i<=res; i++)
{
if(p[i] != p[l-i+1])
{
return false;
}
}
return true;
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
memset(ne, 0, sizeof ne);
scanf("%s", &s);
scanf("%s", &p);
int cnt = 0, k = 0;
n = strlen(s);
m = strlen(p);
init();
if(!fan(m))
{
puts("NO");
if(t)
{
puts("");
}
continue;
}
for(int i=1, j=0; i<=n; i++)
{
while(j && s[i] != p[j+1])
{
j = ne[j];
}
if(s[i] == p[j+1])
{
j++;
}
if(j == m)
{
j = ne[j];
cnt++;
a[k++] = i - m + 1;
a[k++] = i;
i = i - m + 1;
}
}
puts("YES");
printf("%d\n", cnt);
for(int i=0; i<k; i+=2)
{
printf("%d %d\n", a[i], a[i+1]);
}
if(t)
{
puts("");
}
}
return 0;
}
KMP算法板子题