Gym-100676F Palindrome

原题连接:https://odzkskevi.qnssl.com/1110bec98ca57b5ce6aec79b210d2849?v=1491063604

题意:

  多组输入,每一次输入一个n(字符串的长度),一个m(下面m条关系),一个字符串s,m条关系(要求x, y位的字符相等)。

  字符串中有一个或者多个'?' ,'?'可以随机填26个小写英文字母。问你这样的字符串可以有多少种填写方法。

解题思路:

  这一道题,用并查集的方法可以很快的解决。

  因为第i个字符是一定与第n-1-i个字符相同的(i从0开始),加上m条要求之后,就可以获得多个集合,每一个集合都是要求相同的字符。

  选择父亲的时候有讲究,尽量选择是字符作为祖先,'?' 插入到祖父的下面。

  然后就是便利处理一下,把可以确定的 '?' 转换成字母。(只有全部是 '?' 的集合不能转换成字母)

  最后就是遍历一下在字符串中 '?' 的集合的个数,答案就出来了。

 

****************************************************************************************************

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <sstream>
#include <algorithm>
using namespace std;
#define pb push_back
#define mp make_pair
#define mset(a, b)  memset((a), (b), sizeof(a))
//#define LOCAL
typedef long long LL;
const int inf = 0x3f3f3f3f;
const int maxn = 50000+10;
const int mod = 1e9+7;
char s[maxn];
int father[maxn];
int vis[maxn];
int findfa(int x)
{
    return father[x]==-1?  x : father[x] = findfa(father[x]);
}
void uni(int x, int y)
{
    int fa1 = findfa(x);
    int fa2 = findfa(y);
    if(fa1!=fa2){
        if(s[fa1]=='?')     father[fa1] = fa2;
        else      father[fa2] = fa1;
    }
}
int main()
{
    #ifdef LOCAL
        freopen("input.txt" , "r", stdin);
    #endif // LOCAL
    int T;
    cin >> T;
    while(T--){
        int n, m, x, y, flag = 1, num=0;
        mset(father, -1);
        mset(vis, 0);
        scanf("%d%d%s",&n,&m, s);
        for(int i=0;i<n;i++)  uni(i, n-1-i);
        for(int i = 0;i<m;i++){
            scanf("%d%d", &x, &y);
            uni(--x, --y);
        }

        for(int i=0;i<n;i++){
            int x = findfa(i);
            if(s[i] == '?' && s[x] != '?')  s[i] = s[x];
            if(s[i] !='?' && s[x] !='?' && s[i]!=s[x])  {flag=0;break;}//如果字母和字母不对应,直接错误。
        }
        if(!flag)   printf("0\n");
        else{
            for(int i=0;i<n;i++){
                if(s[i]=='?' && father[i] == -1){
                    num++;
                }
            }
            LL ans = 1LL;
            for(int i =0 ;i<num;i++)    ans = (1LL*ans*26 )%mod;
            printf("%lld\n", ans);
        }
    }
    return 0;
}

 

****************************************************************************************************

posted @ 2017-04-04 20:18  Dh_q  阅读(317)  评论(0编辑  收藏  举报