D. Irreducible Anagrams
題意
若兩個字符串中每個字符的個數都是一樣的,則稱他們互為\(anagrams\)。現在定義兩個字符串s,t是\(reducible~anagram\)的,必須滿足下面的條件:
- 將s、t兩個字符串分別拆成k(k>=2)個連續子串
- \(s_1,s_2\cdots s_k\) 按順序排列構成s
- \(t_1,t_2\cdots t_k\) 按順序排列構成t
- \(\forall i \in [1,k],都有s_i 是 t_i 的anagrams\)
現在給了一個字符串,每次詢問它的一個字串是否存在一個\(irreducible~anagram\)(請注意這些概念必須是以s是t的\(anagrams\)前提下進行的)
分析
對於每個詢問的字符串s,是否存在一個字符串t,使得t是s的\(irreducible~anagram\).分析題目條件可以將問題轉換為:在t和s的任意等長前綴中,它們的字符集的個數必須是不同的(也就是確保它們不是\(anagrams\))
我們聲明滿足下面條件的字符串存在\(irreducible~anagram\)
- 長度等於1
- 首字符和尾字符不同
- 字符串包含至少三種不同的字符
求證這些條件后,利用前綴和的技巧可以很容易的解決本題。下面試證一下:
- 長度等於1,那么就無法找到一個 k(k>=2) ,所以它的\(irreducible~anagram\)就是它本身
- \(s[1] \neq s[n]\) 即首字符和尾字符不同,我們可以盡量靠前的將所有同\(s[n]\)一樣的字符寫在前面。然后剩下的字符隨便放置即可。可以想到對於任意的\(k\in[1,n-1]\),都滿足\(s[1..k]\)與\(t[1..k]\)的字符集不同。
- 字符串包含至少三種不同的字符,並且\(s[1] = s[n]\)。可以找到一個最大的\(j\)滿足\(s[j]\neq s[n]\)。可以把所以同\(s[j]\)一樣的字符放到最前面,然后緊挨着中間放置所有同\(s[n]\)的字符,因為不同字符個數大於等於3,所以現在最后面肯定還有空位,將剩余的字符隨意放置在最后面即可。可以想到構成的這樣的一個串,一定滿足任意前綴字符集不等。
到此為止就可以放心做題了,但試圖證明一下為何\(s[1] = s[n]~~and~~不同字符個數等於2\)的情況為何找不到。
假設字符只有a和b兩種,而且\(s[1]=s[n]=a\),那么我們構造出來的串必須滿足任意前綴中\(b\)的個數,都大於\(s\)對應前綴中b的個數。那么考慮\(s\)中最后出現\(b\)的位置\(x\),可以想到\(s[1..x-1]\)前綴比\(t[1..x-1]\)少一個\(b\),而\(s[x]=b\)得出現使得\(t[x]\)必須再放置一個\(b\),這樣才能滿足任意前綴中b得個數都要比s多,但此時已經沒有\(b\)可以放了(因為\(s[1..x-1]\)就已經多放了一個b)所以在\(x\)這個位置,無法構造。
const int N = 200010 + 5;
char s[N];
int n, sum[N][26], q, l, r, cnt[26];
int main() {
scanf("%s", s+1);
n = strlen(s + 1);
for (int i = 1; i <= n;i++){
memcpy(sum[i], sum[i - 1], sizeof sum[i]);
sum[i][s[i] - 'a']++;
}
scanf("%d", &q);
while(q--){
scanf("%d%d", &l, &r);
if(r - l == 0){
puts("YES");
continue;
}
int x = 0;
for (int i = 0; i < 26;i++){
cnt[i] = sum[r][i] - sum[l - 1][i];
if(cnt[i])
x++;
}
if(s[l] == s[r] && x <= 2){
puts("NO");
}else
puts("YES");
}
return 0;
}