KMP = =

本文介绍了一种利用KMP算法解决周期串问题的方法。通过分析字符串的前缀性质,可以找出所有可能的循环节及其最大重复次数。文章提供了一个简洁的C++实现示例。

模板:

//s[]是长文本,p[]是模式串,n是s的长度,m是p的长度
求模式串的Next数组
int i,j;
for(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;
}

//匹配
int i,j;
for(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];
		//匹配成功后的逻辑 
	}
} 

题目1:

Period

题目大意:

有多组测试用例,第一行为字符串长度,第二行为字符串,则对字符串的每一个前缀,若存在循环节且循环次数>1,输出长度和最大的循环次数;

每组测试用例后空一行;

SampleInput

3

aaa

12

aabaabaabaab

0

SampleOutput

Test case #1

2 2

3 3

Test case #2

2 2

6 2

9 3

12 4

写在前面:

Substr(i,j)表示的子串s[i...j].
这里的下标从1开始.
i的上一个匹配:一个位置j,满足Substr(1,j) == substr()
下面黑线表示字符串,其中红框中包含的字符相等(这是自然,同一个字符串嘛).
 

还要满足

(注意啦 两条黑线表示同一个字符串,只是位置不同)

下面图中红框中都表示相同

思路:

这题也可算是"拍大腿"系列了吧?其实你看看下面代码,真的很简单,关键就是如何推出这个结论.
(我不用next/fail,用了f做数组名,希望大家不要看不习惯,意思是一样的)

粉色部分也表示相同.这很明显,因为字符是一一对应的嘛(同一个字符串位置相同,长度相同的字符串当然一样).
由于红框内完全相同,还可以

 

继续对应!灰线表示在原字符串中是对应的.
还可以对应! 

可能就会出现这样的情况!(当然可能最前面不够长度)
因此,只要f[i] > 0,前面肯定有循环节!(只不过不知道是否完整,bb|abb|abb|abb这样也看作是)而且循环节长度为.因此只要判断循环节长度能否将长度整除即可.

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;

char s[N];
int f[N];

int main()
{
	int i;
	int n,k = 0;
    while(cin >> n && n != 0)
	{
        int t = 0;
        cin >> s + 1;
		k ++;
        cout << "Test case #" << k << endl;
        f[1] = 0;
        for (i = 2; i <= n ; i ++ )
		{
            while (s[i] != s[t + 1] && t != 0)  t = f[t];
            if ( s[i] == s[t + 1] )  t++;
            f[i] = t;
            if(f[i] != 0 && i % ( i -  f[i] ) == 0)  cout << i << ' ' << i / ( i - f[i] ) << endl;
        }
        cout << endl;
    }
    return 0;
}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

21RGHLY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值