大致的思路与过程
#include<iostream>
using namespace std;
const int N=100010,M=1000010;
char q[N],s[M];
int ne[N];//保存next数组
int main()
{
int n,m;
cin>>n>>q+1>>m>>s+1;//下标均从1开始
for(int i=2,j=0;i<=n;i++)
//j表示匹配成功的长度,i表示q数组中的下标,因为q数组的下标是从1开始的,只有1个时,一定为0,所以i从2开始
{
while(j&&q[i]!=q[j+1]) j=ne[j];
//如果不行可以换到next数组
if(q[i]==q[j+1]) j++;
//成功了就加1
ne[i]=j;
//对应其下标
}
//j表示匹配成功的长度,因为刚开始还未开始匹配,所以长度为0
for(int i=1,j=0;i<=m;i++)
{
while(j&&s[i]!=q[j+1]) j=ne[j];
//如果匹配不成功,则换到j对应的next数组中的值
if(s[i]==q[j+1]) j++;
//匹配成功了,那么j就加1,继续后面的匹配
if(j==n)//如果长度等于n了,说明已经完全匹配上去了
{
printf("%d ",i-j);
//因为题目中的下标从0开始,所以i-j不用+1;
j=ne[j];
//为了观察其后续是否还能跟S数组后面的数配对成功
}
}
return 0;
}
谢谢你,伊雷娜
太妙了
终于懂next数组咋实现的了 orz
tql,大佬。
简洁明了,终于看懂啦
j不可以从1开始吗
printf i-j 是什么意思啊
只输出了一次啊
为什么可以输出 起始位置和末位位置
好奇怪的问题,题目只要求输出起点,你说的是起点终点只是因为样例巧合而已
不是末位位置,两个都是起始位置,题目要求输出每次匹配成功后的起点
我想一下午了,明明next数组的初始条件为n[1] = 0 , n[2] = 1 ,为什么y总代码里的,n[2] 有可能会等于 0 呢?
去看浏览量第一的那位大佬
确实简洁明了,tql
每次听不懂的时候,看你的题解总能看懂。哈哈,tql。
去掉printf()最后的 j = ne[j] 也正确,您能说下什么情况必须加上j=ne[j] 呢
emmm,这样可以减少复杂度啊,一串匹配成功了了,但是后面的匹配成功的字符也可能有一部分在这段匹配成功的串里面;
例如
abababab
abab
匹配成功
然后可以直接这样
abababab
···abab
还可以防止下一轮匹配时j+1越界
这写的也太好了吧!赞!这是看的你的第三个还是第四个题解,已经成为粉丝了。
谢谢啦(๑•̀ㅂ•́)و✧
棒
orz做的太认真啦