hdu模版水题目2896

没啥好说的。代码注释,可以秒懂

//照打的。跟模板的差别是引入了used数组和一个flag标记
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int maxn = 510*200;
int ch[maxn][128],fail[maxn],end[maxn];
int root,sz,cnt;
char str[10010];
bool used[510];

int newnode(){
    memset(ch[sz],-1,sizeof(ch[sz]));//初始化为-1
    end[sz] = 0;
    return sz++;
}

void init(){
    sz = 0;
    root = newnode();
}

void insert(char *str,int id){
    int len = strlen(str);
    int now = root;
    for(int i = 0;i < len;i++){
        int &tmp = ch[now][str[i]];
        if(tmp == -1)   tmp = newnode();
        now = tmp;
    }
    end[now] = id;//记录当前单词的id
}

void getfail(){
    queue<int> q;
    fail[root] = root;
    for(int i = 0;i < 128;i++){
        int &tmp = ch[root][i];
        if(tmp == -1)   tmp = root;
        else{
            fail[tmp] = root;
            q.push(tmp);
        }
    }
    while(!q.empty()){
        int now = q.front();q.pop();
        for(int i = 0;i < 128;i++){
            if(ch[now][i] == -1){
                ch[now][i] = ch[fail[now]][i];
            }else{
                fail[ch[now][i]] = ch[fail[now]][i];
                q.push(ch[now][i]);
            }
        }
    }
}
//传入的id是为了输出时的方便
void query(char *str,int id){
    int len = strlen(str);
    int now = root;
    int flag = 0;
    memset(used,0,sizeof(used));
    for(int i = 0;i < len;i++){
        now = ch[now][str[i]];
        int tmp = now;
        //以前的代码是这样的:
        /*
          while(tmp != root && val[tmp]){
            val[tmp];
            val[tmp] = 0;
           tmp = fail[tmp];
          }
           */
//在这里行不通,因为为了避免重复把标记改动了,对另外一个单词进行查询的时候就出错
        while(tmp != root){
            //如果是单词末尾id!=0
            if(end[tmp]){
                //标记改为1
                flag = 1;
                //此处used标为1
                used[end[tmp]] = 1;
            }
            tmp = fail[tmp];
        }
    }
    //表示在此串中存在单词
    if(flag){
        cnt++;
        printf("web %d:",id);
        //遍历一遍,输出used标为1的id
        for(int i = 0;i < 510;i++){
            if(used[i]) printf(" %d",i);
        }
        printf("\n");
    }
}

int main(){
    init();
    int n,m;
    scanf("%d",&n);
    for(int i = 1;i <= n;i++){
        scanf("%s",str);
        insert(str,i);
    }
    getfail();
    cnt = 0;
    scanf("%d",&m);
    for(int i = 1;i <= m;i++){
        scanf("%s",str);
        query(str,i);
    }
    printf("total: %d\n",cnt);
    return 0;
}

hdu模版水题目2896

时间: 2024-10-19 05:01:10

hdu模版水题目2896的相关文章

HDU-1042-N!(Java大法好 &amp;&amp; HDU大数水题)

N! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 64256    Accepted Submission(s): 18286 Problem Description Given an integer N(0 ≤ N ≤ 10000), your task is to calculate N! Input One N in o

HDU 4968 (水dp 其他?)

1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <vector> 5 #include <map> 6 using namespace std; 7 const int inf = 0x3f3f3f3f; 8 const int MAX = 200+10; 9 double GPA[10],dp1[20][30000],dp2[20][30000

nyoj 96 一个水题目

虽然很简单,发现自己用内存太高了了,算了,我就是这水平了. 描述 已知w是一个大于10但不大于1000000的无符号整数,若w是n(n≥2)位的整数,则求出w的后n-1位的数. 输入 第一行为M,表示测试数据组数.接下来M行,每行包含一个测试数据. 输出 输出M行,每行为对应行的n-1位数(忽略前缀0).如果除了最高位外,其余位都为0,则输出0. 样例输入 4 1023 5923 923 1000 样例输出 23923230 #include<iostream> using namespace

hdu 4416 水题 浙大计算机研究生复试上机考试-2005年 可是发现自己写代码有问题

Spring3与Hibernate4整合时出现了nested exception is java.lang.NoClassDefFoundError: Lorg/hibernate/cache/CacheProvider. hibernate3的时候,用spring来控制sessionfactory用的可以是org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean,因为用的是hibernate4所以照猫画

HDU-1037-Keep on Truckin&#39;(HDU最水的题没有之一,为了练英语就来吧)

Keep on Truckin' Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 10324    Accepted Submission(s): 7147 Problem Description Boudreaux and Thibodeaux are on the road again . . . "Boudreaux, we ha

HDU 4920 水

矩阵乘法 因为答案要MOD3,所以矩阵中会有很多值为0,对这些不乘就行了,,,,,,,这样也能水过... BUT : 这样写会超时: for (int i=1; i<=n; i++) for (int j=1; j<=n; j++) for (int k=1; k<=n; k++) c[i][j]+=a[i][k]*b[k][j]; 这样写就能过: for (int k=1; k<=n; k++) for (int i=1; i<=n; i++) for (int j=1;

HDU 4915 水

'?'可以任意改变成'(' 或者')',问序列有可行解,可行解是否唯一 首先先判断是否有解 判断是否为Many,记录每个位置的左边和右边各需要多少个'('或')' 左边所需'('若正好等于 (i+1)/2,说明若有解则只有唯一解, 右边所需')若正好等于(len-i)/2,说明若有解则只有唯一解, 若均有多解,判断是否相互包含对方 例:((()))变为 (()()): #include "stdio.h" #include "string.h" int a[1000

HDU 4911 水

对于n个数,可以做k次移动,每次移动可以互换相邻位置的两个数,问最少 number of pair (i,j) where 1≤i<j≤n and ai>aj. 如果不移动的话,ans='n个数的逆序对数',移动k次会减少k个 归并排序求逆序对数: #include "stdio.h" #include "string.h" #include "math.h" int b[100010],a[100010],mark[100010];

map水题目

先做一个水题目.为了熟悉map的基本用法.记得在沈阳实训的时候,老师介绍过stl,里头的关联容器之一就是map,其实是是一个绑定索引,我觉得,蛮好用,除了new什么之类的不懂,其余删除,加入基本都会. #include <iostream> #include<map> #include<string> using namespace std; map<string,int>ballon; string a; string maxs; int t,maxi;