zoukankan      html  css  js  c++  java
  • trie(字典树)

    模板题

    由于找不到最直接的模板,就拿了一个最裸的题权当模板

    传送门

    大体思路

    应用&结构:用于实现字符串快速检索的多叉树结构

    总思路其他博客已经很详尽,这里不再赘述(其实懒得画图)

    定义&初始化

    定义trie[SIZE][30](假设只有小写字母),trie[i][j]表示当前在i结点,编号为j的子结点所处的位置,(我们称字符'a'的编号为0,'b'为1,以此类推),即trie是一个用于模拟指针的数组,定义一个特殊的空结点(一般为0),所有的指针均指向空

    定义end[SIZE],end[i]表示下标为i的结点是否为某个字符串的终点

    插入

    void insert(char *s , int siz) {
    	static int top = 1;//trie的第一维最大下标,类似于链式前向星
    	int p = 1;
    	for(int i = 1 ; i <= siz ; i++) {
    		int c = s[i] - 'a';
    		if(trie[p][c] == 0)//如果指向空,则新建结点
    			trie[p][c] = ++top;
    		p = trie[p][c];
    	}
    	vis[p] = false;
    	end[p] = true;
    }
    

    查找(以模板为例)

    int search(char *s , int siz) {
    	int p = 1;
    	for(int i = 1 ; i <= siz ; i++) {
    		p = trie[p][s[i] - 'a'];
    		if(p == 0) return 0;//当前字符串在trie树中不存在
    	}
    	if(end[p] == false) return 0;//WRONG
    	if(vis[p] == true)	return 2;//REPEAT
    	vis[p] = true;//标记当前字符串已经访问过
    	return 1;//OK
    }
    
    

    模板题完整代码

    #include <iostream>
    #include <cstdio>
    #define nn 500010
    using namespace std;
    int sread(char *s) {
    	int siz = 1;
    	do
    		s[siz] = getchar();
    	while(s[siz] < 'a' || s[siz] > 'z');
    	while(s[siz] >= 'a' && s[siz] <= 'z')
    		s[++siz] = getchar();
    	--siz;
    	return siz;
    }
    
    bool vis[nn] , end[nn];
    int trie[nn][30];
    void insert(char *s , int siz) {
    	static int top = 1;
    	int p = 1;
    	for(int i = 1 ; i <= siz ; i++) {
    		int c = s[i] - 'a';
    		if(trie[p][c] == 0)
    			trie[p][c] = ++top;
    		p = trie[p][c];
    	}
    	vis[p] = false;
    	end[p] = true;
    }
    int search(char *s , int siz) {
    	int p = 1;
    	for(int i = 1 ; i <= siz ; i++) {
    		p = trie[p][s[i] - 'a'];
    		if(p == 0) return 0;
    	}
    	if(end[p] == false) return 0;//WRONG
    	if(vis[p] == true)	return 2;//REPEAT
    	vis[p] = true;
    	return 1;//OK
    }
    
    int n , m;
    char s[nn];
    int main() {
    	cin >> n;
    	for(int i = 1 ; i <= n ; i++) {
    		int siz = sread(s);
    		insert(s , siz);
    	}
    	cin >> m;
    	for(int i = 1 ; i <= m ; i++) {
    		int siz = sread(s);
    		int res = search(s , siz);
    		if(res == 0)
    			puts("WRONG");
    		else if(res == 1)
    			puts("OK");
    		else
    			puts("REPEAT");
    			
    	}
    	return 0;
    }
    
  • 相关阅读:
    ORACLE之常用FAQ V1.0二(构架系统) (1)
    如何快速杀去世占用过多本钱(CPU,内存)的数据库历程
    Eclipse快捷键大全
    (收藏)STL MAP 详解
    怎么在安装目录下创建一个文件
    MFC自绘属性的总结
    文件夹总结
    公元纪年转换为干支纪年
    重载运算符operator
    VS2005快捷键大全
  • 原文地址:https://www.cnblogs.com/dream1024/p/14004776.html
Copyright © 2011-2022 走看看