題目描述
小可愛是個可愛的女孩子(nzdl)。
衆所周知,小可愛在物競初賽時候有兩道大題沒有做出來,所以,可愛的小可愛(qwq)便沉浸在了毒瘤之中——無法接受在任何地方看到"suqingnianloveskirito"這個東西。然而,這時候從SD某處送來了一封安慰信(情書),信的內容是一個26個小寫拉丁字母組成的字符串s。這封信提前被wyxdrqc劫了下來(沒錯,就是這個劫),他打開了這封信,結果發現了滿篇的"suqingnianloveskirito"所以他想篡改這封信。
由於他的能力有限,所以他只能把這個字符串的其中兩個位置上的字符互換,而且只能操作一次。
他現在想問你,通過他的操作能不能使"suqingnianloveskirito"不是這個字符串的子串。
輸入描述
一行一個字符串s
輸出描述
如果他能通過只交換其中的兩個位置上的字符使"suqingnianloveskirito"不是交換後的字符串的子串,則在第一行輸出一個Yes,之後一行輸出兩個數d1,d2,表示你的方案是把原字符串在位置d1和位置d2上的字符互換,字符串的第一個字符的位置是1。
如果他不管交換那兩個字符都不能滿足條件,直接輸出一行No。
題解
對字符串pattern=“suqingnianloveskirito”,進行kmp前綴處理獲得next數組,然後讓輸入字符串s進行kmp匹配,返回s中含有n個字符串pattern,並記錄第一次和第二次子串的首位置的下標。
因爲只能交換字符串s的中的兩個字符,故
①n>2時,NO
②n=2時,YES,可交換第一個子串的第一個字符和第二個子串的第二個字符
③n=1時,在從子串中首位置和字符串s首位置開始一個一個交換後嘗試kmp字符串匹配,直到交換出符合條件的位置
④n=0時,若s的長度小於pattern的長度,故肯定存在,隨機交換即可;若s的長度大於pattern的長度,就可以嘗試s[0]與s[1],s[0]與s[2]…s[0]與s[s.size()-1],s[1]與s[2],s[1]與s[3]交換,直到嘗試出kmp字符串匹配返回匹配成功次數爲0爲止
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e6+7;
int nt[MAX];
int a=0,b=0;
void kmp_next(string pattern,int next[])
{
int len=pattern.size();
next[0]=-1;
for(int i=0,j=-1;i<len;)
{
if(j==-1||pattern[i]==pattern[j])
{
next[++i]=++j;
}
else
j=next[j];
}
}
int kmp(string s,string pattern,int next[])
{
int ls=s.size(),lp=pattern.size(),flag=0;
for(int i=0,j=0;i<ls;)
{
if(j==-1||s[i]==pattern[j]){
i++,j++;
}
else j=next[j];
if(j==lp){
flag++;
j=0;
if(flag==1)a=i-lp;
else if(flag==2)b=i-lp;
}
}
return flag;
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
string s,pattern="suqingnianloveskirito";
cin>>s;
if(s.size()<pattern.size()){
cout<<"Yes"<<endl;
cout<<1<<" "<<2;
return 0;
}
else{
kmp_next(pattern,nt);
int n=kmp(s,pattern,nt);
if(n>2){
cout<<"No";
return 0;
}
else if(n==2){
cout<<"Yes"<<endl;
cout<<a+1<<" "<<b+2;
return 0;
}
else if(n==1){
int f=0;
for(int i=a;i<a+pattern.size();i++)
{
for(int j=0;j<s.size();j++)
{
if(i!=j&&s[i]!=s[j])
{
swap(s[i],s[j]);
if(kmp(s,pattern,nt)==0){
cout<<"Yes"<<endl;
cout<<i+1<<" "<<j+1;
return 0;
}
else swap(s[i],s[j]);
}
}
}
cout<<"No";
}
else {
int f=0;
for(int i=0;i<s.size();i++)
{
for(int j=i+1;j<s.size();j++)
{
if(s[i]!=s[j])
{
swap(s[i],s[j]);
if(kmp(s,pattern,nt)==0){
cout<<"Yes"<<endl;
cout<<i+1<<" "<<j+1;
return 0;
}
else swap(s[i],s[j]);
}
}
}
cout<<"No";
}
}
return 0;
}