zoukankan      html  css  js  c++  java
  • hdu2457 Trie图+dp

    hdu2457

    给定n个模式串, 和一个文本串

    问如果修改最少的字符串使得文本串不包含模式串, 

    输出最少的次数,如果不能修改成功,则输出-1

    dp[i][j] 表示长度为i的字符串, 到达状态j(Trie图中的结点)所需要修改的最少次数

    那么dp[0->n][0->size] = INF ,  dp[0][root] = 0,  n代表字符串长度, size代表状态数

    那么答案就是  min{dp[n][size]}

    我们根据模式串所建的Trie图, 进行模拟构造不包含模式串的字符串

    从第一个字符串开始构造,依次递增,在构造此字符的同时,比较是否和输入串的该字符串相等,

    如果相等,则表示该位置的字符不需要改变, 如果不同,则表示该位置的字符需要改变

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <stdlib.h>
      4 #include <algorithm>
      5 #include <iostream>
      6 #include <queue>
      7 #include <stack>
      8 #include <vector>
      9 #include <map>
     10 #include <set>
     11 #include <string>
     12 #include <math.h>
     13 using namespace std;
     14 #pragma warning(disable:4996)
     15 typedef long long LL;                   
     16 const int INF = 1<<30;
     17 /*
     18 
     19 */
     20 struct Node
     21 {
     22     int fail, next[4];
     23     bool isWord;
     24     void init()
     25     {
     26         fail = -1;
     27         isWord = false;
     28         for (int i = 0; i < 4; ++i)
     29             next[i] = -1;
     30 
     31     }
     32 }Trie[1000 + 10];
     33 int size;
     34 char str[1000 + 10];
     35 int dp[1000 + 10][1000 + 10];
     36 int getCode(char ch)
     37 {
     38     if (ch == 'A')
     39         return 0;
     40     if (ch == 'G')
     41         return 1;
     42     if (ch == 'C')
     43         return 2;
     44     return 3;
     45 }
     46 void insert(int root, char str[])
     47 {
     48     int cur = root;
     49     for (int i = 0; str[i]; ++i)
     50     {
     51         int idx = getCode(str[i]);
     52         if (Trie[cur].next[idx] == -1)
     53         {
     54             Trie[size].init();
     55             Trie[cur].next[idx] = size++;
     56         }
     57         cur = Trie[cur].next[idx];
     58     }
     59     Trie[cur].isWord = true;
     60 }
     61 void makeFail(int root)
     62 {
     63     queue<int> q;
     64     int cur;
     65     for (int i = 0; i < 4; ++i)
     66     if (Trie[root].next[i] == -1)
     67         Trie[root].next[i] = root;
     68     else
     69     {
     70         Trie[Trie[root].next[i]].fail = root;
     71         q.push(Trie[root].next[i]);
     72     }
     73     while (!q.empty())
     74     {
     75         cur = q.front();
     76         q.pop();
     77         for (int i = 0; i < 4; ++i)
     78         {
     79             if (Trie[Trie[cur].fail].isWord)
     80                 Trie[cur].isWord = true;
     81             if (Trie[cur].next[i] == -1)
     82                 Trie[cur].next[i] = Trie[Trie[cur].fail].next[i];
     83             else
     84             {
     85                 Trie[Trie[cur].next[i]].fail = Trie[Trie[cur].fail].next[i];
     86                 q.push(Trie[cur].next[i]);
     87             }
     88         }
     89     }
     90 }
     91 
     92 //dp[i][j] 表示长度为i的字符串到达状态j,所要修改的次数,  如果状态为危险状态,那么肯定是INF
     93 int solve(int root, char *str)
     94 {
     95     int n = strlen(str);
     96     for (int i = 0; i <= n; ++i)
     97     for (int j = 0; j < size; ++j)
     98         dp[i][j] = INF;
     99 
    100     dp[0][root] = 0;
    101     for (int i = 0; i < n; ++i)
    102     for (int j = 0; j < size; ++j)
    103     if (dp[i][j] < INF)
    104     {
    105         for (int k = 0; k < 4; ++k)
    106         {
    107             int next = Trie[j].next[k];
    108             if (Trie[next].isWord) continue;
    109             int tmp;
    110             if (k == getCode(str[i]))
    111                 tmp = dp[i][j];//如果构造出的字符和输入字符相同,就不需要改变该位置的字符串
    112             else
    113                 tmp = dp[i][j] + 1;//否则,要改变该位置的字符串
    114             dp[i + 1][next] = min(dp[i + 1][next], tmp);
    115         }
    116     }
    117     int ans = INF;
    118     for (int j = 0; j < size; ++j)
    119         ans = min(ans, dp[n][j]);
    120     if (ans == INF) ans = -1;
    121     return ans;
    122 }
    123 
    124 int main()
    125 {
    126     int n, k = 1;
    127     char segment[20+10];
    128     while(scanf("%d", &n), n)
    129     {
    130         Trie[0].init();
    131         Trie[0].fail = 0;
    132         size = 1;
    133         for (int i = 0; i < n; ++i)
    134         {
    135             scanf("%s", segment);
    136             insert(0, segment);
    137         }
    138         makeFail(0);
    139         scanf("%s", str);
    140         printf("Case %d: %d
    ", k, solve(0, str));
    141         k++;
    142 
    143     }
    144     return 0;
    145 }
  • 相关阅读:
    Seial port API and tool
    Simple HTTPD
    VC与Cygwin的结合
    zlib
    嵌入式开发系统编程文件格式解析
    ZB4O
    Wireshark基本介绍和学习TCP三次握手
    freeware
    Console2 A Better Windows Command Prompt
    iniparser
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4593976.html
Copyright © 2011-2022 走看看