zoukankan      html  css  js  c++  java
  • 2020杭电多校第二场 hdu6774 String Distance

    题目链接

    http://acm.hdu.edu.cn/showproblem.php?pid=6774

    题目大意

    给定一个字符串 A 和一个字符串 B , 有 Q 次查询

    每次查询给出一段区间 [L , R] , 问 A[L...R] 和 B串的 LCS 为多少

    解题思路 

    定义 M 为 B 串的长度 , 先预处理跑一遍序列自动机 NEX 

    其中 nex[ i ][ j ] 表示字符串 A 的 [ i + 1 , n ] 区间第一次出现字符 j 的位置

    定义 dp [ i ][ j ] , 其含义为 —— 和B的前 i 个字符 , 匹配了长度为 j 的 LCS 的最短 A 前缀

    即 LCS( B[1...i] , A[L...X] ) = j , X 为最小取值 , dp[ i ][ j ] = X 

    再定义 pre = dp[ i - 1 ][ j - 1 ] , 那么

    ①、dp[ i ][ j ] = NEX[ pre ][ b[i] - 'a' ] 

    ②、dp[ i ][ j ] = dp[ i - 1 ][ j ]

    当 dp[ i ][ j ] 的值小于等于 R 时 ,  LCS = j 合法

    所以最后我们只要从 M 到 1 找到第一个 j 使得 dp[ M ][ j ] <= R 即可

    AC_Code

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 3e5 + 10 , M = 30;
    int dp[N][M] , nex[N][M];
    char a[N] , b[M];
    signed main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0) , cout.tie(0);
        int T ;
        cin >> T ;
        while(T --)
        {
            cin >> a + 1 >> b + 1;
            int n = strlen(a + 1) , m = strlen(b + 1) , q;
            for(int j = 0 ; j < 26 ; j ++) nex[n][j] = n + 1;
            for(int i = n - 1 ; i >= 0 ; i --)
            {
                for(int j = 0 ; j < 26 ; j ++) nex[i][j] = nex[i + 1][j];
                nex[i][a[i + 1] - 'a'] = i + 1; 
            }
            cin >> q; 
            while(q --)
            {
                int l , r , lcs = 0;
                cin >> l >> r;
                for(int i = 0 ; i <= m ; i ++) for(int j = 0 ; j <= m ; j ++) dp[i][j] = 0x3f3f3f3f; 
                for(int i = 0 ; i <= m ; i ++) dp[i][0] = l - 1;
                for(int i = 1 ; i <= m ; i ++)
                    for(int j = 1 ;  j <= i ; j ++)
                    {
                        if(dp[i - 1][j] <= r) dp[i][j] = min(dp[i][j] , dp[i - 1][j]);
                        int pre = dp[i - 1][j - 1];
                        if(pre <= r && nex[pre][b[i] - 'a'] != 0 && nex[pre][b[i] - 'a'] <= r)
                        dp[i][j] = min(dp[i][j] , nex[pre][b[i] - 'a']);
                    }
                   for(int i = m ; i >= 1 ; i --) if(dp[m][i] <= r) { lcs = i ; break ; }
                cout << r - l + 1 + m - 2 * lcs << '
    ';    
            }
        }
        return 0;
    }
  • 相关阅读:
    C#中HashTable的用法
    JS、C#编码解码
    javascipt取整数四舍五入
    Oracle中的不等于号
    MD5加密函数
    汉字转成拼音
    按日期生成惟一的编号
    将access数据转换成oracle数据
    TOAD Menu Shortcuts 快捷键
    请求方法总结
  • 原文地址:https://www.cnblogs.com/StarRoadTang/p/13369855.html
Copyright © 2011-2022 走看看