码迷,mamicode.com
首页 > 其他好文 > 详细

CF-1291 D - Irreducible Anagrams

时间:2020-02-03 12:03:02      阅读:61      评论:0      收藏:0      [点我收藏+]

标签:技巧   line   continue   没有   lse   ons   写在前面   lin   red   

D. Irreducible Anagrams

题意

若两个字符串中每个字符的个数都是一样的,则称他们互为\(anagrams\)。现在定义两个字符串s,t是\(reducible~anagram\)的,必须满足下面的条件:

  1. 将s、t两个字符串分别拆成k(k>=2)个连续子串
  2. \(s_1,s_2\cdots s_k\) 按顺序排列构成s
  3. \(t_1,t_2\cdots t_k\) 按顺序排列构成t
  4. \(\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
  2. 首字符和尾字符不同
  3. 字符串包含至少三种不同的字符

求证这些条件后,利用前缀和的技巧可以很容易的解决本题。下面试证一下:

  1. 长度等于1,那么就无法找到一个 k(k>=2) ,所以它的\(irreducible~anagram\)就是它本身
  2. \(s[1] \neq s[n]\) 即首字符和尾字符不同,我们可以尽量靠前的将所有同\(s[n]\)一样的字符写在前面。然后剩下的字符随便放置即可。可以想到对于任意的\(k\in[1,n-1]\),都满足\(s[1..k]\)\(t[1..k]\)的字符集不同。
  3. 字符串包含至少三种不同的字符,并且\(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;
}

CF-1291 D - Irreducible Anagrams

标签:技巧   line   continue   没有   lse   ons   写在前面   lin   red   

原文地址:https://www.cnblogs.com/1625--H/p/12254833.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!