• G


    在这里插入图片描述

    题意

    有AGTC四种字符,一开始有一个空串,每次操作,可以在首或尾加任意个字符,或者将已有字符镜面复制(左右两种复制方法),要求最少的操作步数使得得到给出的字符串

    Solution:

    我们要知道我们要求的是什么,是每一给回文串的所需要的最少的构造操作加上n-这个串的长度

    然后就考虑如何求前者

    题解:https://blog.csdn.net/nudt_spy/article/details/100061078

    Code;

    #include<bits/stdc++.h>
    #define N 100010
    #define INF 0x3f3f3f3f
    #define eps 1e-6
    #define pi 3.141592653589793
    #define mod 777777777
    #define P 1000000007
    #define LL long long
    #define pb push_back
    #define fi first
    #define se second
    #define cl clear
    #define si size
    #define lb lower_bound
    #define ub upper_bound
    #define bug(x) cerr<<#x<<"      :   "<<x<<endl
    #define mem(x,y) memset(x,0,sizeof(int)*(y+3))
    #define sc(x) scanf("%d",&x)
    #define scc(x,y) scanf("%d%d",&x,&y)
    #define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
    using namespace std;
    typedef  pair<int,int> pp;
    char s[N];
    int ans;
    int tot;
    
    struct PAM {
        int next[N][4] ;//next指针,next指针和字典树类似,指向的串为当前串两端加上同一个字符构成
        int fail[N] ;//fail指针,失配后跳转到fail指针指向的节点
        int cnt[N]; //表示节点i表示的回文串的个数(建树时求出的不是完全的,最后count()函数跑一遍以后才是正确的)
        int num[N] ; //表示以节点i表示的最长回文串的最右端点为回文串结尾的回文串个数(包括本身)。
        int len[N] ;//len[i]表示节点i表示的回文串的长度
        int s[N] ;//存放添加的字符
        int half[N];
        int dp[N];
        int last ;//指向上一个字符所在的节点,方便下一次add
        int n ;//字符数组指针
        int p ;//节点指针
        //r为结尾的回文串的长度一定可以分成logn段等差数列
        inline int newnode ( int l ) {//新建节点
            for ( int i = 0 ; i < 4 ; ++ i ) next[p][i] = 0 ;
            cnt[p]= 0 ;
            num[p] = 0 ;
            len[p] = l ;
            return p ++ ;
        }
        inline void init () {//初始化
            p = 0 ;
            newnode (  0 ) ;
            newnode ( -1 ) ;
            last = 0 ;
            n = 0 ;
            s[n] = -1 ;//开头放一个字符集中没有的字符,减少特判
            fail[0] = 1 ;
            half[0]=half[1]=1;
        }
        inline int get_fail ( int x ) {//和KMP一样,失配后找一个尽量最长的
            while ( s[n - len[x] - 1] != s[n] ) x = fail[x] ;
            return x ;
        }
        inline void add ( int c ) {
            // c -= 'a' ;
            s[++ n] = c ;
            int cur = get_fail ( last ) ;//通过上一个回文串找这个回文串的匹配位置
            if ( !next[cur][c] ) {//如果这个回文串没有出现过,说明出现了一个新的本质不同的回文串
                int now = newnode ( len[cur] + 2 ) ;//新建节点
                fail[now] = next[get_fail ( fail[cur] )][c] ; 
                next[cur][c] = now ;
                if (len[now]==1) half[now]=0;else{
                    int pos=half[cur];
                    while ( s[n - len[pos] - 1] != s[n]||len[pos]+2>len[now]/2 ) pos = fail[pos] ;
                    half[now]=next[pos][c];
                }
                if (len[now]&1)
                    dp[now]=dp[fail[now]]+len[now]-len[fail[now]];
                else
                    if (len[now]<=2) dp[now]=len[now];
                else
                    dp[now]=min(dp[cur]+1,dp[half[now]]+len[now]/2-len[half[now]]+1);
            }
            last = next[cur][c] ;
            ans=min(ans,dp[last]+tot-len[last]);
        }
    }A;
    
    int main(int argc, char const *argv[])
    {
        int T; sc(T);
        while(T--){
            scanf("%s",s+1);
            int n=strlen(s+1); tot=n;
            A.init();
            ans=1e9;
            for(int i=1;i<=n;i++) {
                int x;
                if (s[i]=='A') x=0;else
                if (s[i]=='G') x=1;else
                if (s[i]=='C') x=2;else
                                x=3;
                A.add(x);
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    mysql 数据库 II(数据类型)
    mysql 数据库 I
    网络协议
    Python 类IV(类成员,异常处理等)
    Python 类III(三大特性,约束,super)
    Python 类II
    类加载机制
    Java新篇章之集合
    Java 类类型之 String 类型
    java 多态
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/11580860.html
Copyright © 2020-2023  润新知