【UVA】11468-Substring(AC自动机)

AC自动机的题,需要注意的,建立失配边的时候,如果结点1失配边连到的那个结点2,那个结点2是一个单词的结尾,那么这个结点1也需要标记成1(因为可以看成,这个结点包含了这个单词),之后在Trie树上进行行走,每次走到下一个可以走的结点。


14378527 11468 Substring Accepted C++ 0.585 2014-10-19 10:35:00

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn = 444;
const int max_size = 66;
const int maxd = 111;
int M,Case = 1;
int ch[max_size];
double P[max_size];
int index(int c){
    if(c >= 'A' && c <= 'Z') return c - 'A';
    if(c >= 'a' && c <= 'z') return c - 'a' + 26;
    if(c >= '0' && c <= '9') return c - '0' + 52;
}
struct Trie{
    int next[maxn][max_size];
    int fail[maxn];
    int val[maxn];
    int vis[maxn][maxd];
    double dp[maxn][maxd];
    int sz,root;
    int newnode(){
        val[sz] = 0;
        memset(next[sz],-1,sizeof(next[sz]));
        sz ++;
        return sz - 1;
    }
    void init(){
       sz = 0;
       root = newnode();
       memset(vis,0,sizeof(vis));
       return;
    }
    void insert(char *str){
        int now = root;
        int L = strlen(str);
        for(int i = 0; i < L; i++){
            int e = index(str[i]);
            if(next[now][e] == -1)
               next[now][e] = newnode();
            now = next[now][e];
        }
        val[now] = 1;
        return;
    }
    void build(){
        queue<int>q;
        fail[root] = root;
        for(int i = 0; i < max_size ; i++)
            if(next[root][i] != -1){
                fail[next[root][i]] = root;
                q.push(next[root][i]);
            }
            else
                next[root][i] = root;
        while(!q.empty()){
            int now = q.front(); q.pop();
            for(int i = 0; i < max_size ; i++){
                if(next[now][i] == -1)
                   next[now][i] = next[fail[now]][i];
                else{
                    q.push(next[now][i]);
                    fail[next[now][i]] = next[fail[now]][i];
                    val[next[now][i]] |= val[fail[next[now][i]]];
                }
            }
        }
        return;
    }
    double DP(int pos,int L){
        if(!L) return 1.0;
        if(vis[pos][L])
            return dp[pos][L];
        vis[pos][L] = 1;
        double &ans = dp[pos][L];
        ans = 0.0;
        for(int i = 0; i < M; i++){
            int e = ch[i];
            if(!val[next[pos][e]])
                ans += P[i] * DP(next[pos][e],L - 1);
        }
        return ans;
    }
}ac;
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        ac.init();
        int K;
        scanf("%d",&K);
        for(int i = 0; i < K; i++){
            char str[maxn];
            scanf("%s",str);
            ac.insert(str);
        }
        ac.build();
        scanf("%d",&M);
        for(int i = 0; i < M; i++){
            char str[maxn];
            scanf("%s%lf",str,&P[i]);
            ch[i] = index(str[0]);
        }
        int L;
        scanf("%d",&L);
        double ans = ac.DP(0,L);
        printf("Case #%d: %.6f\n",Case++,ans);
    }
    return 0;
}

这段代码是一个解析GPS数据的函数,主要作用是将GPS数据缓冲区中的信息解析并存储到指定的变量中。函数中的变量和结构体成员的含义如下: - subString:用于存储GPS数据缓冲区中的子字符串; - subStringNext:用于存储GPS数据缓冲区中的下一个子字符串; - i:循环计数器,用于遍历GPS数据缓冲区中的各个子字符串; - Save_Data:一个结构体类型的变量,用于存储解析后的GPS数据; - Save_Data.isGetData:一个布尔类型的变量,用于表示是否已经获取到完整的GPS数据; - Save_Data.GPS_Buffer:一个字符数组类型的变量,用于存储GPS数据缓冲区中的数据; - Save_Data.UTCTime:一个字符数组类型的变量,用于存储GPS数据中的UTC时间; - Save_Data.latitude:一个字符数组类型的变量,用于存储GPS数据中的纬度信息; - Save_Data.N_S:一个字符数组类型的变量,用于存储GPS数据中的N/S标志; - Save_Data.longitude:一个字符数组类型的变量,用于存储GPS数据中的经度信息; - Save_Data.E_W:一个字符数组类型的变量,用于存储GPS数据中的E/W标志。 函数的执行流程如下: - 如果已经获取到完整的GPS数据,则将isGetData标志位清零,并开始解析数据; - 使用strstr函数查找GPS数据缓冲区中的第一个逗号,并将其后面的字符串存储到subString中; - 根据i的值,分别解析UTC时间、纬度信息、N/S标志、经度信息、E/W标志等数据,并将其存储到对应的变量中; - 解析完成后,函数执行完毕。 需要注意的是,该函数中存在一些问题,比如usefullBuffer数组只有2个字节大小,可能无法存储完整的子字符串;另外,函数中没有对解析错误进行处理,需要根据具体情况进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值