kmp——可爱即正义
题目描述
小可爱是个可爱的女孩子(nzdl)。
众所周知,小可爱在物竞初赛时候有两道大题没有做出来,所以,可爱的小可爱(qwq)便沉浸在了毒瘤之中——无法接受在任何地方看到"suqingnianloveskirito"这个东西。然而,这时候从SD某处送来了一封安慰信(情书),信的内容是一个26个小写拉丁字母组成的字符串s。这封信提前被wyxdrqc劫了下来(没错,就是这个劫),他打开了这封信,结果发现了满篇的"suqingnianloveskirito"所以他想篡改这封信。
由于他的能力有限,所以他只能把这个字符串的其中两个位置上的字符互换,而且只能操作一次。
他现在想问你,通过他的操作能不能使"suqingnianloveskirito"不是这个字符串的子串。
输入描述
一行一个字符串 s。
输出描述
如果他能通过只交换其中的两个位置上的字符使"suqingnianloveskirito"不是交换后的字符串的子串,则在第一行输出一个Yes,之后一行输出两个数d1,d2,表示你的方案是把原字符串在位置d1和位置d2上的字符互换,字符串的第一个字符的位置是1。
如果他不管交换那两个字符都不能满足条件,直接输出一行No。
示例 1
输入
suqingnianloveskiritosuqingnianloveskiritosuqingnianloveskiritothemostimportantthingneedsaidatleastthreetimes
输出
No
示例 2
输入
suqingnianloveskiritosomuch
输出
Yes
1 2
备注
对于 100% 数据,有字符串的长度 <= 1000000
对于 10% 数据,有测试数据的答案 = 样例。
并且你的方案中,不能出现 d1 = d2 的情况。
如果有多种可行方案,输出任何一种即可得分。
#include<bits/stdc++.h>
using namespace std;
const int N = 1000005;
string t,s;
int nxt[N],f[N],a,b;
void getNext()
{
int slen=s.length();
int j=0;
int k=-1;
nxt[0]=-1;
while(j<slen){
if(k==-1||s[j]==s[k]){
++k;
++j;
nxt[j]=k;
f[k]++;
}
else{
k=nxt[k];
}
}
}
int kmp()
{
int i=0;
int j=0;
int tlen=t.length();
int slen=s.length();
int flag=0;
while(i<tlen){
if(j==-1 || t[i]==s[j]){
i++;
j++;
}
else{
j=nxt[j];
}
if(j==slen){
flag++;
j=nxt[j];
if(flag==1){
a=i-slen;
}
if(flag==2){
b=i-slen;
}
}
}
return flag;
}
int main()
{
cin>>t;
s="suqingnianloveskirito";
if(t.size()<s.size()){ // 当输入字符串长度小于字符串 s 的长度时,能够满足条件
cout<<"Yes"<<endl;
cout<<1<<" "<<2<<endl;
}
else{
getNext();
int n=kmp();
if(n>2){ // 如果输入的字符串中存在两个以上子串与字符串 s 匹配,则不能满足条件
cout<<"No"<<endl;
}
else if(n==2){ // 当输入的字符串存在两个子串与字符串 s 匹配时,能够满足条件
cout<<"Yes"<<endl;
cout<<a+1<<" "<<b+2<<endl;
}
else{ // 当输入的字符串只存在一个子串与字符串 s 匹配时,能够满足条件
cout<<"Yes"<<endl;
cout<<a+1<<" "<<a+2<<endl;
}
}
return 0;
}