Trie入门题HDU - 1671-Phone List)——(前缀统计)

Phone List

Description:
给定n个字符串,问当中是否有字符串是其他字符串的前缀。

思路1:
对于每个字符串,判断它的每一个字符(除去最后一个字符)是否是其他字符串的结尾。
思路2;
对于每个子串的结尾,判断它是否是其他字符串的中间字符。

思路1:

#include<stdio.h>
#include<iostream>
#include<cmath>
#include<math.h>
#include<string>
#include<string.h>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<map>
#define ms0(a) memset(a,0,sizeof(a))
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;

const int maxnode = 1e5+5;

int trie[maxnode][11],tot=0,strend[maxnode];
char dir[maxnode][15];
void insert(char* str)
{
    int len =(int)strlen(str),p=0;
    for(int k=0;k<len;k++)
    {
        int ch = str[k]-'0';
        if(trie[p][ch]==0)
        {
            trie[p][ch] = ++tot;
        }
        p = trie[p][ch];
    }
    strend[p]++;
}

bool search(char* str)
{
    int len = (int)strlen(str),p=0;
    for(int k=0;k<len-1;k++)
    {
        p = trie[p][str[k]-'0'];
        if(strend[p])
            return false;
    }
    return true;
}

int main(){
    int ncase,n;
    cin>>ncase;
    while (ncase--)
    {
        scanf("%d",&n);
        ms0(trie);ms0(strend);
        tot=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%s",dir[i]);
            insert(dir[i]);
        }
        bool flag = true;
        for(int i=1;i<=n;i++)
        {
            if(!search(dir[i]))
            {
                flag = false;
                break;
            }
        }
        if(flag)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

思路2:

#include<stdio.h>
#include<iostream>
#include<cmath>
#include<math.h>
#include<string>
#include<string.h>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<map>
#define ms0(a) memset(a,0,sizeof(a))
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;

const int maxnode = 1e5+5;

int trie[maxnode][11],value[maxnode],tot=0;
char dir[maxnode][15];
void insert(char* str)
{
    int len =(int)strlen(str),p=0;
    for(int k=0;k<len;k++)
    {
        int ch = str[k]-'0';
        if(trie[p][ch]==0)
        {
            trie[p][ch] = ++tot;
        }
        p = trie[p][ch];
        value[p]++;
    }
}

int search(char* str)
{
    int len = (int)strlen(str),p=0;
    for(int k=0;k<len;k++)
    {
        p = trie[p][str[k]-'0'];
    }
    return value[p]-1;
}

int main(){
    int ncase,n;
    cin>>ncase;
    while (ncase--)
    {
        scanf("%d",&n);
        ms0(trie);ms0(value);
        tot=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%s",dir[i]);
            insert(dir[i]);
        }
        bool flag = true;
        for(int i=1;i<=n;i++)
        {
            if(search(dir[i]))
            {
                flag = false;
                break;
            }
        }
        if(flag)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

前缀统计

Description:
给定n个字符串(可能有相同的),接下来进行M次询问,每次询问给定字符串T,求这n个字符串中有多少个字符串是T的前缀。
字符串的根节点不能只记录一个true或false,还应该记录次数,
查询的时候将经过的根节点的权值累加即可。

int trie[maxnode][11],tot=0,strend[maxnode];
void insert(char* str)
{
    int len =(int)strlen(str),p=0;
    for(int k=0;k<len;k++)
    {
        int ch = str[k]-'0';
        if(trie[p][ch]==0)
        {
            trie[p][ch] = ++tot;
        }
        p = trie[p][ch];
    }
    strend[p]++;
}

int search(char* str)
{
    int len = (int)strlen(str),p=0;
    int ans = 0;
    for(int k=0;k<len;k++)
    {
        p = trie[p][str[k]-'0'];
        ans += strend[p];
    }
    return ans;
}
发布了67 篇原创文章 · 获赞 0 · 访问量 1482

猜你喜欢

转载自blog.csdn.net/qq_44846324/article/details/104669775