E2. Unforgivable Curse (hard version)

Problem - E2 - Codeforces

问题描述:给两个字符串和一个k。如果下标i,j满足|i - j| == k or |i - j| == k + 1,则可以swap(s[i], s[j]),s为两个字符串之一。

思路:如果<i,z> <z,j>可行,那么<i,j>一定也是可行的。发现对于一个连通块而言,这一个连通块内的字符总是可以进行交换。如果对于一个连通块来说,两个字符串在这个连通块中的字符种类对应的个数是相同的,那么总是可以经过若干操作,使这两个字符串在连通块中对应的下标的元素相等。

因此dfs找连通块,之后判断这个连通块中字符种类及其对应的个数是否相等,相等则可能相同,不等则一定不相等。

AC代码:

const int N = 2e5 + 21;
char s1[N], s2[N];
int fa[N]; // 并查集
// vis数组是判断连通块是否遍历过,st是判断这个点是否在找连通块中被遍历过
bool vis[N], st[N];
int find(int u) {
    
    return fa[u] == u ? u : fa[u] = find(fa[u]); }
void inpfile();
void solve() {
    
    
    int n,k; cin>>n>>k;
    // 初始化
    for(int i = 1;  i <= n; ++i) fa[i] = i, vis[i] = 0, st[i] = 0;
    cin>>s1 + 1>> s2 + 1;
    bool fg = true;
    map<int,int> mii;
    // 找连通块
    auto dfs = [&] (auto &&dfs, int u) -> void {
    
    
        if(st[u]) return ;
        st[u] = 1;
        int len = 0;
        for(int j = 0; j < 4; ++j) {
    
    
            len = (k + j%2) * (j < 2 ? 1 : -1);
            int pos = u + len;
            // 上面操作是得到 位置 
            // pos - k  |  pos + k
            // pos + k + 1 |  pos - (k + 1)

            // 位置不合法
            if(pos < 1 || pos > n) continue;

            // 找父亲
            int pfa = find(pos), ifa = find(u);
            if(pfa != ifa) {
    
    
                // 注意一定是将 pos的指向u的。因为后面遍历时,是根据第一个的位置来判断的
                fa[pfa] = ifa;
                /**
                 * 1 -- > 2 --> 3 -- > 4
                 * 将2的父亲指向1的父亲,这样在后面判断是否遍历过就行。
                 * 
                 * 由于我用的vis数组判断,如果用的是用map或者什么的,将每个点都进行个判断也行
                */

               // 判断字符种类及其个数是否相同
               // 这里用 一个字符串进行++操作,一个字符串进行--操作,等价于次
                mii[s1[pos]] ++;
                mii[s2[pos]] --;
                dfs(dfs, pos);
            }
        }
    };
    for(int i = 1; i <= n; ++i) {
    
    
        // 由于我是用这个父亲值进行判断的
        if(vis[find(i)]) continue;
        vis[find(i)] = 1;
        // 每次要清空
        mii.clear();
        
        // 第一个i,没有对应上,要手动设置上
        mii[s1[i]]++;
        mii[s2[i]]--;
        dfs(dfs, i);
        
        // 判断字符种类及其对应个数是否相同
        for(auto t: mii) {
    
    
            if(t.vs != 0) {
    
    
                fg = false;
            }
        }
    }
    puts(fg ? "YES" : "NO");

}

猜你喜欢

转载自blog.csdn.net/qq_63432403/article/details/132712062