Codeforces Round #726 (Div. 2) E2. Erase and Extend (Hard Version) (字串,思維.kmp)
阿新 • • 發佈:2021-06-28
-
題意:給你一個字串,選擇一個字首,使其不斷複製,直到\(len>=k\),如果\(len>k\),刪去多餘的尾部,問你能得到的字典序最小的字串.
-
題解:基本思路和E1一樣,比較後面的字元和\(s[1]\),大於就直接break,小於就繼續,等於的話,我們要先找到\(s_{1...x}\)和\(s_{i,i+1,..,i+x}\)的相同字首,看第一個不相同的字元,如果\(s_{x+1}<s_{i+x+1}\)那麼我們就繼續選,否則直接break.這個相同字首後第一個不同字元,不難發現,這不就是kmp找next陣列的過程嗎?直接s+s上kmp就行.
-
題解:
#include <bits/stdc++.h> #define ll long long #define fi first #define se second #define pb push_back #define me memset #define rep(a,b,c) for(int a=b;a<=c;++a) #define per(a,b,c) for(int a=b;a>=c;--a) const int N = 1e6 + 10; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; using namespace std; typedef pair<int,int> PII; typedef pair<ll,ll> PLL; ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;} ll lcm(ll a,ll b) {return a/gcd(a,b)*b;} int n,k; string s; int ne[N]; void get_nxt(){ for(int i=2,j=0;i<=2*n;++i){ while(j!=0 && s[i]!=s[j+1]) j=ne[j]; if(s[i]==s[j+1]) j++; ne[i]=j; } } int main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); cin>>n>>k; cin>>s; s=" "+s+s; get_nxt(); int len=n; for(int i=1;i<=2*n;++i){ int j=ne[i-1]+1; if(s[j]<s[i]){ len=i-j; break; } } for(int i=1,j=1;i<=k;++i){ cout<<s[j]; j++; if(j>len) j=1; } return 0; }