牛客18984 可愛即正義 KMP

可愛即正義 KMP二星水題 傳送門

題目描述

小可愛是個可愛的女孩子(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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章