2018 RUN@KAIST Winter Curling Competition women's finals game is now ongoing. On the frozen "duck pond" of KAIST, Korean women curling team is having a fierce competition with team from country Jwepan!
There are N curling stones on the "duck pond". As the competition is really fierce, every stone is placed in a line from a mark. The leftmost stone is closest from the mark, while the rightmost stone is farthest from the mark. Stones are either from Korean team ('1'), or from Jwepan team ('0'). Those arrangement of stones can be represented with length N binary sequence.
After the end of Pyeongchang Olympics, Korean team had gone through intensive training. Now with some shoutings(?), team member "Youngmi", who carries the curling stone, can bounce away some consecutive stones and place her stone in that position. Formally, Korean team can pick any subsegment in a binary string (which can be empty), and replace it into a single digit "1".
Korean team is a master in a curling strategy, and they knew the best strategy for one turn is to make the string lexicographically maximal! For the fast decision making in this game, they want to find a fastest algorithm which can find this. Help the Korean team to win the competition!
String s = s1s2... sn of length n is lexicographically larger than string t = t1t2... tm of length m, if one of the following holds:
- There exists some i such that, s1 = t1, s2 = t2, ..., si - 1 = ti - 1, and si > ti.
- n > m and, s1 = t1, s2 = t2, ..., sm = tm.
In the first line, N, the number of stones is given. (1 ≤ N ≤ 1, 000, 000)
In the second line, A single binary string of length N, which consists of '0' or '1' is given. This string indicates the owner of each curling stone, in the order of distance from the mark. There are no quotes or blanks given in the string.
Print two integer S, L. This means that Youngmi removed L stones after Sth character. If there is more than one correct answer, print any. (0 ≤ S, L ≤ N)
8 10101101
1 3
5 11111
0 0
题意:给一个01串,可以替换一个任意长度的连续串为一个1,问最终的字典序最大的串?
思路:一道水题愣是弄了一个上午,注意连续串长度可以为空,第一个0肯定是作为起点,然后找到其后字典序最大的后序,将两者中间的替换成1就是最佳答案,后缀数组就行。
# include <bits/stdc++.h>
using namespace std;
const int N = 1e6+30;
int wa[N],wb[N],wsf[N],wv[N],sa[N];
int s[N],ss[N], a[N],n,id[N],kk;
char str[N];
int cmp(int *r,int a,int b,int k){return r[a]==r[b]&&r[a+k]==r[b+k];}
void getsa(int *r,int *sa,int n,int m)
{
int i,j,p,*x=wa,*y=wb,*t;
for(i=0; i<m; i++) wsf[i]=0;
for(i=0; i<n; i++) wsf[x[i]=r[i]]++;
for(i=1; i<m; i++) wsf[i]+=wsf[i-1];
for(i=n-1; i>=0; i--) sa[--wsf[x[i]]]=i;
j=p=1;
for(; p<n; j*=2,m=p)
{
for(p=0,i=n-j; i<n; i++) y[p++]=i;
for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;
for(i=0; i<n; i++) wv[i]=x[y[i]];
for(i=0; i<m; i++) wsf[i]=0;
for(i=0; i<n; i++) wsf[wv[i]]++;
for(i=1; i<m; i++) wsf[i]+=wsf[i-1];
for(i=n-1; i>=0; i--) sa[--wsf[wv[i]]]=y[i];
t=x;x=y;y=t;
x[sa[0]]=0;
for(p=1,i=1; i<n; i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)? p-1:p++;
}
}
int main()
{
int n, cnt=0;
scanf("%d",&n);
scanf("%s",str);
int k = 0;
while(k<n && str[k]=='1') ++k;
if(k==n) return 0*puts("0 0");
for(int i=k;i<n;++i) s[cnt++] = str[i]-'0'+1;
s[cnt] = 0;
getsa(s,sa,cnt+1,3);
printf("%d %d\n",k,sa[cnt]);
return 0;
}