zoukankan      html  css  js  c++  java
  • 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
    ");
            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
    ", ans);
            }
        }
        return 0;
    }

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

  • 相关阅读:
    漫谈 C++ 的 内存堆 实现原理
    我发起了一个 .Net 开源 数据库 项目 SqlNet
    谈谈 数据库原理
    论 数据库 B Tree 索引 在 固态硬盘 上 的 离散存储
    论 东坡肉 和 红烧肉 的 区别
    浅谈 操作系统原理
    引子 初识
    P2P Downloader
    利用 MessageRPC 和 ShareMemory 来实现 分布式并行计算
    MessageRPC
  • 原文地址:https://www.cnblogs.com/denghaiquan/p/6666292.html
Copyright © 2011-2022 走看看