hdu1671 字典树 入门

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define kind 26
const int MAXN = 10000000;

struct node
{
    int count; //是否为单词最后一个节点
    node *next[26];//Trie每个节点的26个子节点
    node *fail; //失败指针
};

node *q[MAXN]; //队列,采用bfs 构造失败指针
char keyword[55];//输入单词 模式串
char str[1000010];// 需要查找的 主串
int head,tail;//队列 头尾指针
node *root;

void insert(char *word,node *root)
{
     int index,len;
     node *p = root,*newnode;
     len = strlen(word);
     for(int i=0 ;i < len ; i++ )
     {
         index=word[i]-'a';
         if(!p->next[index])//该字符节点不存在,加入Trie树中
         {
           // 初始化 newnode 并 加入 Trie 树
            newnode=(struct node *)malloc(sizeof(struct node));
            for(int j=0;j<26;j++) newnode->next[j]=0;
            newnode->count=0;newnode->fail=0;
            p->next[index]=newnode;
         }
         p=p->next[index];//指针移动至下一层
     }
     p->count++;  //单词结尾 节点 count + 1 做标记
}

void build_ac_automation(node *root)
{
     head=0;tail=1;
     q[head]=root;
     node *temp,*p;
     while(head<tail)//bfs构造 Trie树的失败指针
     {
       //算法类似 kmp ,这里相当于得到 next[]数组
       //重点在于,匹配失败时,由fail指针回溯到正确的位置

        temp=q[head++];
         for(int i=0;i< 26 ;i ++)
         {
             if(temp->next[i])//判断实际存在的节点
             {
                 // root 下的第一层 节点 都 失败指针都 指向root
                 if(temp==root) {

                 temp->next[i]->fail=root;
                 }
                 else {
                    //依次回溯 该节点的父节点的失败指针
                   //知道某节点的next[i]与该节点相同,则
                   //把该节点的失败指针指向该next[i]节点
                   //若回溯到 root 都没有找到,则该节点
                   //的失败指针 指向 root

                    p=temp->fail;//temp 为节点的父指针
                    while(p){
                       if(p->next[i]){
                       temp->next[i]->fail=p->next[i];
                       break;
                       }
                       p=p->fail;
                    }
                    if(!p)temp->next[i]->fail=root;
                 }
                 //每处理一个点,就把它的所有儿子加入队列,
                 //直到队列为空
                 q[tail++]=temp->next[i];
             }
         }
     }
}
int query(node *root)//类似于 kmp算法。
{
    //i为主串指针,p为匹配串指针
    int i,cnt=0,index,len=strlen(str);
    node *p=root;
    for(i=0; i < len ;i ++)
    {
       index=str[i]-'a';
                        //由失败指针回溯寻找,判断str[i]是否存在于Trie树种
       while(!p->next[index] && p != root)p=p->fail;
       p=p->next[index];//找到后 p 指向该节点

       //指针回为空,则没有找到与之匹配的字符

       if(!p)p=root;//指针重新回到根节点root,下次从root开始搜索Trie树

       node *temp=p;//匹配该节点后,沿其失败指针回溯,判断其他节点是否匹配

       while(temp != root )//匹配 结束控制
       {
           if(temp->count>=0)//判断 该节点是否被访问
           {
              //统计出现的单词个数cnt,由于节点不是单词结尾时count为0,
             //故 cnt+=temp->count; 只有 count >0时才真正统计了单词个数

             cnt+=temp->count;
              temp->count=-1; //标记已访问
           }
           else break;//节点已访问,退出循环
           temp=temp->fail;//回溯失败指针继续寻找下一个满足条件的节点
       }
    }
    return cnt;
}
int main()
{
    int i,t,n,ans;
    scanf("%d",&t);
    while(t--)
    {
       root=(struct node *)malloc(sizeof(struct node));
       for(int j=0;j<26;j++) root->next[j]=0;
       root->fail=0;
       root->count=0;
       scanf("%d",&n);
       getchar();
       for(i=0;i<n;i++)
       {
           gets(keyword);
           insert(keyword,root);
       }
       build_ac_automation(root);
       gets(str);
       ans=query(root);
       printf("%d\n",ans);
    }
    return 0;
}



//hdu2222需要做的。


很好的字符串处理题目
求多个字符串的公共字串,由于数据比较小,可以暴力求解。

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

char str[15][80];
int n, m;

int main()
{
    scanf("%d", &n);
    while(n--) {

        scanf("%d", &m);
        getchar();
      for(int i = 0; i < m; i++) {

            scanf("%s", str[i]);
      }
       char s1[70];
       char ans[70];
       int t = 0;
       int len = strlen(str[0]);
      for(int i = 0; i < len; i++) {  

            for(int j = i + 2; j < len; j++) { //枚举所以大于3的字串,

                strncpy(s1, str[0]+i, j - i + 1); //此函数拷被后,没在字符串后面加‘\0',
                s1[j-i + 1] = '\0';               //需手动加上,
               // printf("%s\n", s1); 
                int flag = 1;
                for(int k = 1; k < m&&flag; k++) {

                    if(strstr(str[k], s1) == NULL) { //简单的匹配查找函数。

                        flag = 0;

                    }
                }
              //  printf("%d\n", flag);
                if(flag) {

                    if(t == 0) {

                        strcpy(ans, s1); //函数的复制。
                        t++;

                    }else {

                       int ans1 = strlen(ans);
                       int slen = strlen(s1);
                       if(ans1 < slen) {

                            strcpy(ans, s1);
                       }else if(ans1 == slen && strcmp(ans, s1) > 0) {

                            strcpy(ans, s1);
                       }
                    }

                }
            }
      }
      if(t != 0) {

        printf("%s\n", ans);
      }else {

        printf("no significant commonalities\n");
      }
    }
    return 0;
}

关于字符串处理专题的总结:
poj 1002

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cstring>

using namespace std;
/*应注意
2
0000000
0000000
output
000-0000 2
*/
//用sort排序老超时,
/*
现在想想题目还是很简单的,
方法1 
将输入的电话号码转换成整数, hash就好了,
注意:如果用整数输出,
 printf("%03d-%04d %d\n", i/10000, i%10000, num[i]);
 对七位全为0的整数输出。

*/


char map[26] = {'2', '2', '2', '3', '3', '3', '4', '4', '4',
                '5', '5', '5', '6', '6', '6', '7', '0', '7', '7', '8', '8', '8', '9', '9', '9', '0'
               };

char str1[305];
int num[10000005];

int n;


int main()
{
    char str[300];

    while(scanf("%d", &n) != EOF)
    {
        memset(num, 0, sizeof(num));
        int maxn = 0, minn = 10000000;
        int flag = 0;
        for(int i = 0; i < n; i++)
        {

            scanf("%s", str1);
            int k = 0;
            for(int j = 0; str1[j] != '\0'; j++)
            {


                if(str1[j] == '-' || str1[j] == 'Q' || str1[j] == 'Z')
                    continue;
                if(str1[j] >= 'A' && str1[j] <= 'Z')
                {
                    str[k++] = map[str1[j]-'A'];
                }
                if(str1[j] >= '0' && str1[j] <= '9')
                {

                   str[k++] = str1[j];
                }
            }

            str[k] = '\0';

            int ans = atoi(str);

            if(ans > maxn)
                maxn = ans;
            if(ans < minn)
                minn = ans;
            num[ans]++;

        }
        for(int i = minn; i <= maxn; i++) {

            if(num[i] > 1) {
                printf("%03d-%04d %d\n", i/10000, i%10000, num[i]);
                flag = 1;
            }
        }

        if(!flag)
           printf("No duplicates.\n");

    }
    return 0;
}


poj2141

#include <iostream>
#include <cstring>
#include <cstdio>
#include <map>

using namespace std;

char str[30];
char str1[100];

int main()
{
   while(scanf("%s", str) != EOF) {

        map<char,char>m;
        for(int i = 0; i < 26; i++){

            m['a' + i] = str[i];

        }

        getchar();
      gets(str1);

        for(int j = 0; str1[j]; j++) {

            if(str1[j] == ' '){

                printf(" ");
            } else if(str1[j] >= 'a' && str1[j] <= 'z'){

                printf("%c", m[str1[j]]);

            }
             else if(str1[j] >= 'A' && str1[j] <= 'Z') {

                printf("%c", m[str1[j] + 32] - 32);
            }

        }

        printf("\n");
   }
    return 0;
}

poj3080
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

char str[15][80];
int n, m;

int main()
{
    scanf("%d", &n);
    while(n--) {

        scanf("%d", &m);
        getchar();
      for(int i = 0; i < m; i++) {

            scanf("%s", str[i]);
      }
       char s1[70];
       char ans[70];
       int t = 0;
       int len = strlen(str[0]);
      for(int i = 0; i < len; i++) {  //枚举第一串长度大于3的字串。

            for(int j = i + 2; j < len; j++) {

                strncpy(s1, str[0]+i, j - i + 1); //截取str[0]中i 到j-i + 1 这一段的字符;
                s1[j-i + 1] = '\0';          //需要手动加上'\0'结束符。
               // printf("%s\n", s1);
                int flag = 1;
                for(int k = 1; k < m&&flag; k++) {

                    if(strstr(str[k], s1) == NULL) { //用该字串和其它串进行匹配。

                        flag = 0;

                    }
                }
              //  printf("%d\n", flag);
                if(flag) {

                    if(t == 0) {

                        strcpy(ans, s1);
                        t++;

                    }else {

                       int ans1 = strlen(ans);
                       int slen = strlen(s1);
                       if(ans1 < slen) {

                            strcpy(ans, s1);
                       }else if(ans1 == slen && strcmp(ans, s1) > 0) {

                            strcpy(ans, s1);
                       }
                    }

                }
            }
      }
      if(t != 0) {

        printf("%s\n", ans);
      }else {

        printf("no significant commonalities\n");
      }
    }
    return 0;
}


hdu1671 字典树

/*
2
3
911
97625999
91125426
5
113
12340
123440
12345
98346
*/
//题意给出机组单词, 如果不存在一个单词是另一个单词的前缀,输出YES or 输出NO;

#include <string>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <iostream>

using namespace std;

struct node
{
    bool end;
    int a[10];
};

bool x;
int ptr;
node list[100000];

void Init()
{
    x=true;
    ptr=0;
    for(int i=0;i<100000;i++)
    {
        list[i].end=false;
        for(int j=0;j<10;j++)
            list[i].a[j]=-1;
    }
}

void Insert(char*s)
{
    bool z=false;
    bool y=false;
    int now=0;
    int len=strlen(s);
    for(int i=0;i<len;i++)
    {
        if(list[now].a[s[i]-'0']==-1)
        {
            z=true;
            list[now].a[s[i]-'0']=++ptr;
            now=ptr;
        }
        else
        {
            now=list[now].a[s[i]-'0'];
            if(list[now].end) y=true;
        }
    }
    list[now].end=true;
    x=(!y)&&z;
}

int main()
{
    int t,n;
    char s[11];
    scanf("%d",&t);
    while(t--)
    {
        Init();
        scanf("%d",&n);
        while(n--)
        {
            scanf("%s",&s);
            if(x) Insert(s);
        }
        if(x) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CSDN IT狂飙上传的代码均可运行,功能ok的情况下才上传的,直接替换数据即可使用,小白也能轻松上手 【资源说明】 基于MATLAB实现的数字调制就是把数字基带信号的频谱搬移到高频处,形成适合在信道中传输的带通信号基本的数字调制方式有振幅键控(ASK)、频移键控(FSK)、绝对相移键控(PSK)、相对(差分)相移键控(DPSK)在接收端可以基于想干解调或非相干解调还原数字基带信号+使用说明文档 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2020b;若运行有误,根据提示GPT修改;若不会,私信博主(问题描述要详细); 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可后台私信博主; 4.1 期刊或参考文献复现 4.2 Matlab程序定制 4.3 科研合作 功率谱估计: 故障诊断分析: 雷达通信:雷达LFM、MIMO、成像、定位、干扰、检测、信号分析、脉冲压缩 滤波估计:SOC估计 目标定位:WSN定位、滤波跟踪、目标定位 生物电信号:肌电信号EMG、脑电信号EEG、心电信号ECG 通信系统:DOA估计、编码译码、变分模态分解、管道泄漏、滤波器、数字信号处理+传输+分析+去噪、数字信号调制、误码率、信号估计、DTMF、信号检测识别融合、LEACH协议、信号检测、水声通信 5、欢迎下载,沟通交流,互相学习,共同进步!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值