zoukankan      html  css  js  c++  java
  • Codeforces1263D-Secret Passwords

    题意

    给n个字符串,两个字符串之间如果有相同的字符,那么两个就等价,等价关系可以传递,问最后有多少个等价类。

    分析

    • 考虑并查集或者dfs联通块,如果是并查集的话,对于当前字符串的某个字符,肯定要和这个字符在前面出现的某个字符串合并起来,所以维护每个字符的最后一次出现位置即可。
    • 如果是dfs找联通块,建图就是把26个字符看成26个点,然后字符串分别连向这些字符,最后从字符节点dfs标记。

    代码

    • dfs
    #include <bits/stdc++.h>
    using namespace std;
    const int N=2e6+50;
    int n;
    char s[55];
    struct Edge{
        int v,next;
    }e[N*2];
    int cnt,head[N];
    int ind[N];
    void init(){
        cnt=0;
        memset(head,-1,sizeof(head));
    }
    void add(int u,int v){
        e[cnt]=Edge{v,head[u]};
        head[u]=cnt++;
        e[cnt]=Edge{u,head[v]};
        head[v]=cnt++;
    }
    int v[30],vis[N];
    void dfs(int u){
        vis[u]=1;
        for(int i=head[u];i!=-1;i=e[i].next){
            int v=e[i].v;
            if(vis[v]){
                continue;
            }
            dfs(v);
        }
    }
    int main(){
        scanf("%d",&n);
        init();
        for(int i=1;i<=n;i++){
            scanf("%s",s+1);
            int len=strlen(s+1);
            memset(v,0,sizeof(v));
            for(int j=1;j<=len;j++){
                if(!v[s[j]-'a'+1]){
                    ind[s[j]-'a'+1]++;
                    add(26+i,s[j]-'a'+1);
                    v[s[j]-'a'+1]=1;
                }
            }
        }
        int ans=0;
        for(int i=1;i<=26;i++){
            if(ind[i] && !vis[i]){
                dfs(i);
                ans++;
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
    
    • 并查集
    #include <bits/stdc++.h>
    using namespace std;
    const int N=2e6+50;
    int p[N];
    int n;
    char s[55];
    int let[30];
    void init(int n){
        for(int i=1;i<=n;i++){
            p[i]=i;
        }
    }
    int find(int x){
        return x==p[x]?p[x]:p[x]=find(p[x]);
    }
    int main(){
        scanf("%d",&n);
        init(n);
        for(int i=1;i<=n;i++){
            scanf("%s",s+1);
            int len=strlen(s+1);
            for(int j=1;j<=len;j++){
                if(let[s[j]-'a'] && let[s[j]-'a']!=i){
                    int fa=find(let[s[j]-'a']);
                    int fb=find(i);
                    if(fa!=fb){
                        p[fa]=fb;
                    }
                }
                let[s[j]-'a']=max(let[s[j]-'a'],i);
            }
        }
        int ans=0;
        for(int i=1;i<=n;i++){
            if(p[i]==i){
                ans++;
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    div 垂直居中的方法
    vs code添加到鼠标右键
    win10系统迁移到新的硬盘
    使用layui iframe弹层,各弹层之前的传值问题
    layui js动态添加的面板不能折叠
    Nginx系列6:对称加密与非对称加密各自的应用场景
    Nginx系列5:从网络原理来看SSL安全协议
    Nginx系列0:Nginx学习历程
    加扰与加密&解扰与解密
    微信小程序学习过程
  • 原文地址:https://www.cnblogs.com/zxcoder/p/11995022.html
Copyright © 2011-2022 走看看