牛客字符串KMP训练题 可爱即正义
一开始的时候怎么也想不明白,根本就不知道时间复杂度怎么优化,后来在左神左学长的指点下,发现了字符串的模式串是给定的,并且其无法在其本身上找到一段与其本身匹配的地方,也就是说,没有办法在母串上找到多个相互交错的模式串
接下来就简单了,分别讨论母串上找到的模式串有times个的情况
当times>2时,无解了,想想就明白
当times==2时,交换找到的两个的位置的第一个、第二个字符,一定不会换出来模式串,想想就可以明白的
当times==1时,从第一个开始找一个字符与找到的模式串的位置首位相交换,再判断即可
当times==0时,随便交换两个并判断是否会再找到模式串即可
但是这个时间复杂度可能会很大,注意减少匹配的次数
代码:
#include <bits/stdc++.h>
#define ll long long
const int maxn=1e6+7;
using namespace std;
int l1,l2,times=0;
int nxt[maxn],pos[maxn];
char str[maxn],st[maxn]={"suqingnianloveskirito"};
void getnxt(){
nxt[0]=-1;
int i=0,j=-1;
while (i<l2){
if(j==-1 || st[i]==st[j])
nxt[++i]=++j;
else
j=nxt[j];
}
}
void kmp(){
int i=0,j=0;
while (i<l1){
if(j==-1 ||str[i]==st[j])
j++,i++;
else
j=nxt[j];
if(j==l2)
times++,j=0,pos[times]=i-l2;
}
}
int main()
{
scanf("%s",str);
l1=strlen(str),l2=strlen(st);
getnxt();
kmp();
if(times>2){
printf("No\n");
}
else if(times==2){
printf("Yes\n");
printf("%d %d\n",pos[1]+1,pos[2]+2);
}
else if(times==1){
for (int i=pos[1];i<pos[1]+l2;i++)
{
for(int j=0;j<l1;j++)
if(j!=i && str[i]!=str[j]){
swap(str[i],str[j]);
times=0;
kmp();
if(times==0){
printf("Yes\n%d %d\n",i+1,j+1);
return 0;
}
else
swap(str[i],str[j]);
}
}
printf("No\n");
}
else{
for(int i=0;i<l1;i++){
for(int j=i+1;j<l1;j++)
if(str[i]!=str[j])
{
swap(str[i],str[j]);
times=0;
kmp();
if(times==0){
printf("Yes\n%d %d\n",i+1,j+1);
return 0;
}
else
swap(str[i],str[j]);
}
}
printf("No\n");
}
return 0;
}