知识点:考察对next数组的理解:周期性字符串循环节长度 ans 是 n−next[n] ,也可以理解为 n-next 的前缀是最小覆盖子串 ,而当前提为n% ans==0&&next[n] !=0时,循环次数是 n/ans 。
(一般只用到next,不用kmp)
题目1
题意:给你一串字符串。可以在这个字符串左右加上任意字符,使最后求得的字符串可以构成循环。
思路:
用前缀数组可以求得初始字符串的最小循环节。
最小循环节=(原字符串长度-末尾前缀数组值)
然后进行讨论:
如果最小循环节=原子符串长度.说明末尾前缀数组值为0.说明原串中,只能通过复制一次原串得到目标字符串。 ans=原串长度
如果原串长度%最小循环节=0.说明可以通过循环原串中某前缀就可以构成原串,原串已经完成循环。 ans=0
如果不是上面两种情况。说明原串中,有部分不在循环中。可以求得这部分长度为最小循环节-原串长度%最小循环节。我们加上这部分就可以构成循环,满足条件。** ans=最小循环节-原串长度%最小循环节
#include<bits/stdc++.h>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
#define mod 1000000007;
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
const int manx=1e5+5;
ll nexts[manx];
ll n,m,ans,t;
string p,s;
void getnexts()
{
int i=0,j=-1;
nexts[i]=j;
while(i<m){
if(j==-1 || p[i]==p[j]) nexts[++i]=++j;
else j=nexts[j];
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin>>t;
while(t--)
{
cin>>p;
m=p.size();
getnexts();
ll len=m-nexts[m];
if(len!=m && m%len==0) cout<<0<<endl;
else cout<<len-m%len<<endl;
}
return 0;
}
题目2
题意:给一个字符串,求循环个数
#include<string>
#include<iostream>
#include<cstdio>
#define ll long long
#define R register int
#define inf 0x3f3f3f3f
#define mod 1000000007;
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
inline ll read(){
ll s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void put1(){ puts("YES") ;}
void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }
const int manx=1e6+5;
ll nexts[manx];
ll n,m,ans,t;
string p,s;
void getnexts()
{
int i=0,j=-1;
nexts[i]=j;
while(i<m){
if(j==-1 || p[i]==p[j]) nexts[++i]=++j;
else j=nexts[j];
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
while(cin>>p)
{
if(p[0]=='.') break;
m=p.size();
getnexts();
ll len=m-nexts[m];
if(len!=m && m%len==0 ) cout<<m/len<<endl;
else cout<<1<<endl;
}
return 0;
}
这篇博客探讨了如何使用Next数组来处理字符串的循环性质。首先解释了Next数组的概念,即它用于找到字符串的最小循环节。接着,通过两个编程题目展示了如何运用这个概念。题目1要求在不改变字符串内部结构的情况下,找到构建循环字符串所需的最少附加字符数。题目2则要求计算给定字符串的循环次数。当字符串长度能被Next数组计算出的循环节整除时,循环次数为字符串长度除以循环节;否则,循环次数为1。这两个题目都强调了Next数组在字符串处理中的应用。
647

被折叠的 条评论
为什么被折叠?



