Neighboring Characters
Problem Description
Given a string s of length n, let’s define the neighbors of the i-th character ( 1 ≤ i ≤ n 1\le i\le n 1≤i≤n) as follows:
If
1
<
i
<
n
1<i<n
1<i<n, the neighbors of the i-th character are the (i-1)-th character and the (i+1)-th character;
If
i
=
1
i=1
i=1, the neighbors of the 1st character are the 2nd character and the n-th character;
If
i
=
n
i=n
i=n, the neighbors of the n-th character are the (n-1)-th character and the 1st character.
A string s is good, if and only if all the characters in the string are different from their neighbors.
DreamGrid would like to delete k continuous characters from string s to form a new string sk. Note that the n-th character and the 1st character are also continuous (you can consider the string as a ring). Please tell him if it’s possible to make sk a good string for all 0 ≤ k < n 0 \le k <n 0≤k<n.
Input
There are multiple test cases. The first line of the input contains an integer T, indicating the number of test cases. For each test case:
The first and only line contains a string s( 1 ≤ ∣ S ∣ ≤ 1 0 6 1\le|S|\le10^6 1≤∣S∣≤106) consists of lowercase English letters.
It’s guaranteed that the sum of |S| over all test cases will not exceed 1.2 ∗ 1 0 7 1.2 * 10 ^ 7 1.2∗107.
Output
For each test case output one line containing one string of length ∣ S ∣ |S| ∣S∣ consists of ‘0’ and ‘1’. If the i-th (the index starts from 1) character is ‘1’, it is possible to make s i − 1 s_i-1 si−1 a good string; If its ‘0’, it is impossible to make s i − 1 s_i-1 si−1 a good string.
Sample Input
5
abab
aabbaa
abcabc
abcdef
a
Sample Output
1011
000011
110111
111111
1
题意
有一个字符串,它的首尾是相连的,可以删除它连续的k个字符,如果能使所有相邻的字符不相同,则为1,否则为0,对于所有的k(0<=k<len),求出对应的结果。
题解:
暂且不考虑首尾是否相同,考虑让每个段尽可能的长。将串划分为多段
[
l
1
,
r
1
]
,
[
l
2
,
r
2
]
[l_1,r_1],[l_2,r_2]
[l1,r1],[l2,r2]… ,
l
2
=
r
1
+
1
,
l
3
=
r
2
+
1
l_2 = r_1+1, l_3 = r_2+1
l2=r1+1,l3=r2+1 …,注意它是环,所以最后一段可能是
[
l
i
,
n
]
,
[
1
,
r
n
]
[l_i, n], [1, r_n]
[li,n],[1,rn]的形式。
分别考虑每一段,判断段内是否存在删除k个连续字符使首尾不相同(前面的划分已保证其他位置相邻字符不同)。
删除k个连续的字符 = 保留
j
=
l
e
n
−
k
j = len-k
j=len−k个连续的字符,我们将问题转化为考虑是否存在连续j个字符相邻元素不同。
需要j成立,则
s
t
r
[
l
]
!
=
s
t
r
[
l
+
j
−
1
]
,
s
t
r
[
l
+
1
]
!
=
s
t
r
[
l
+
j
]
.
.
.
.
s
t
r
[
r
−
j
+
1
]
!
=
s
t
r
[
r
]
str[l] != str[l+j-1] ,str[l+1] != str[l+j] .... str[r-j+1] != str[r]
str[l]!=str[l+j−1],str[l+1]!=str[l+j]....str[r−j+1]!=str[r]中有一个成立即可,可以看出等式两边分别是一段的前后缀,只需要判断前后缀是否相同即可。
可以利用hash在O(1)时间内判断两段前后缀是否相等。
#include<stdio.h>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<ctype.h>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-6
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = 2000100;
const int mod = 1000000007;
char str[maxn];
LL hs[maxn], ss[maxn];
int ans[maxn];
LL geths(int l, int r);
int main()
{
int t, n, i, j, k;
ss[0] = 1;
for(i=1;i<=maxn-50;i++)
ss[i] = ss[i-1]*26%mod;
scanf("%d", &t);
while(t--)
{
scanf(" %s", str+1);
n = strlen(str+1);
for(i=1;i<=n;i++)
{
ans[i] = 0;
str[i+n] = str[i];
}
hs[0] = 0;
for(i=1;i<=2*n;i++)
hs[i] = (hs[i-1]*26+str[i]-'a'+1)%mod;
int l = 1, r = 1;
while(l<=n)
{
while(str[r]!=str[r+1] && r-l+1<n)
r++;
for(i=0;i<r-l;i++)
if(geths(l, l+i) != geths(r-i, r))
ans[r-l+1-i] = 1;
l = r = r+1;
}
ans[1] = 1;
for(i=n;i>=1;i--)
printf("%d", ans[i]);
printf("\n");
}
return 0;
}
LL geths(int l, int r)
{
LL ks = hs[l-1]*ss[r-l+1]%mod;
return (hs[r]-ks+mod)%mod;
}