P11276 第一首歌 題解

adsd45666發表於2024-11-15

P11276 第一首歌 題解

一道簡單的字串題目。

題目解釋

說求一個最短的字串 \(t\) ,使其滿足對於給定的字串 \(s\)

  • \(s\)\(t\) 的字首。

  • \(s\)\(t\) 的字尾。

  • \(s\) 不為 \(t\)

仔細思考一下,則易得 \(t\) 的最短長度的最大值為 \(s\) 的兩倍。即當 \(s\) 是一個字首字尾不相同的字串時, \(t\) 就是兩個拼在一起的 \(s\)

考慮非特殊情況,那麼也就是刪去第二個累加的 \(s\) 中,與其字尾相同的字首。類似於共用這一部分。

解題思路

觀察到要求相同的字首和字尾,正好在學 KMP 於是這裡使用了其字首陣列解決。那麼問題便簡化了,求出的 \(sum\) 為字首與字尾的最大重合區間長度,接著輸出 \(s\) 除前 \(sum\) 個字元的其他字元即可。

code

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
string s1;
int net[maxn];
void build_kmp(string s){
    net[0]=0,net[1]=0;
    int len=0,i=1;
    for(int i=1;i<s.size();i++){
        int j=net[i];
        while(j&&s[i]!=s[j]){
            j=net[j];
        }
        if(s[i]==s[j]) net[i+1]=j+1;
        else           net[i+1]=0;
    }
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>s1;
    build_kmp(s1);
    cout<<s1;         //第一遍無需修改
    for(int i=net[(int)s1.size()];i<(int)s1.size();i++){
        cout<<s1[i];  //輸出非重複部分
    }
    return 0;
}

相關文章