【题解】 D - Irreducible Anagrams

题目来源:Codeforces Round #616 (Div. 2) - D

题意:

定义两个字符串互为anagrams当且仅当两个串中每个字符的个数是一样的。定义两个字符串s,t,t与s之间为reducible anagram当且仅当:存在分隔方式使得将s,t按此方式各分为至少两个串时,s1与t1、s2与t2…之间都互为anagrams。现给定一个字符串s和q次询问,每次询问s的一个子串,判断是否至少存在一个字符串t使其之间reducible anagram。

思路:

要判断两个字符串s,t之间为reducible anagram,要重点关注其前缀字符集。通过s找到这样一个t,大体思路为:将某些字符放置到字符串开头,使得前缀不满足anagrams。

这样不难想到,当s[l]!=s[r]时,也许可以构造出t。尝试证明:
将所有与s[r]相同的字符放到字符串开头,其他字符任意放置构造t。这样在前缀集的比较中,t总是多出至少一个s[r],所以子串和t之间为reducible anagram。

而当s[l]=s[r]时,若子串中出现至少至少三种不同的字符时,也可以构造出t。证明:
找到最大的i满足i<r且s[i]!=s[r],将所有与s[i]相同的字符放在开头,再接上所有与s[r]相同的字符,其他字符任意放置构造t。不难理解,若想要前缀可以匹配上,至少要到s[i];而此时s[i]后面只剩下与s[r]相同的字符了,t最后是一个与s[r]不相同的字符(至少有三种不同的字符),所以只能到一个字符才可以互为anagrams。

最后加上l=r的情况,同时易证其余情况(l!=r且s[l]=s[r]且最多只有两种不同的字符)一定有能构造一个t与子串互为anagrams。

代码:

#include <iostream>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <cctype>
#include <functional>
#include <string>
#include <cstring>
#include <sstream>
#include <deque>
#define fir first
#define sec second
using namespace std;

typedef long long ll;
typedef pair<int,int> P;
typedef pair<P,int> Q;

const int inf1=1e9+9;
const ll inf2=1e16+9;
const ll mol=1e9+7;
const int maxn=2e5+9;
const ll maxx=1e12+9;

int n,q,l,r;
string s;
vector<int> ar[26];

bool judge()
{
    int cnt=0;
    for(int i=0;i<26;i++)
        if(upper_bound(ar[i].begin(),ar[i].end(),r)-upper_bound(ar[i].begin(),ar[i].end(),l)) cnt++;
    return cnt>=3;
}
int main()
{
    cin>>s; n=s.size();
    for(int i=0;i<n;i++) ar[s[i]-'a'].push_back(i);
    scanf("%d",&q);
    while(q--)
    {
        scanf("%d%d",&l,&r); l--,r--;
        if(l==r||s[l]!=s[r]||judge()) printf("YES\n");
        else printf("NO\n");
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值