实现一个比较高级的字符匹配算法,即一串很长的字符,要求找到符合要求字符的字符串
2015-09-18 09:13
507 查看
一个小的算法题,题目如题。什么意思呢?
就是一个很长的模式串例如“432A5234B5664C3243454”,再给一个目标串“ABC”,只要模式串中某一个字符串同事包含目标串中的每一个元素即可!
要求很低!很明显的用暴力匹配很容易就做出来了,但是暴力匹配算法的时间复杂度很低,是乘方级的(O(n^m))!KMP算法很难处理这种模糊的匹配。
如何才能提高效率呢,利用hash表就很容易解决这个问题,而且是一个相当简单的哈希表,非常有利于新人理解hash表。
由于字符串最多只有255位,所以这个hash表就只有0~255这些元素,根据ASCII表的码值作为hash数组的下标,如果在目标串中存在,相应的位置元素为1,
其余的位置都是0。这样我们可以构建一个数组来统计目标串的字符是否出现在模式串中。
代码时间,首先制作一个hash表,由于在main函数中,我已经将hash表的每一个元素都初始化为0,这样只要将相应位置修改即可:
[plain] view
plaincopyprint?
/*
功能:实现一个比较高级的字符匹配算法,即一串很长的字符,要求找到符合要求字符的字符串
姓名:***
时间:0:10 2014/1/18
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/*制作hash表并初始化*/
void mkHash(char T[],char hash[],int n)
{
if(!T)
{
exit(-1);
}
for (int i = 0 ; i< n ; i++)
{
hash[T[i]] = 1; /*根据ASCII表的码值作为hash数组的下标*/
}
}
下面这个函数就是某个字符是否在hash中出现了
[plain] view
plaincopyprint?
int isExit(char str,char hash[])
{
if(!hash)
{
exit(-1);
}
if(hash[str] == 0)
{
return 0;
}
else
{
return 1;
}
}
接下来这个是就是主要函数了,遍历模式串,主要匹配就输出没有什么难点很容易看得懂:
[plain] view
plaincopyprint?
void getPos(char S[] , int n , char hash[])
{
if(!S && !hash)
{
exit(-1);
}
for (int i=0;i<n;i++)
{
if(hash[S[i]] == 1)
{
printf("%d ",i+1);
hash[S[i]] = 0;
}
}
}
再从main引导:
[plain] view
plaincopyprint?
int main()
{
char S[255];
char T[255];
char hash[255] = {0};
gets(S);
gets(T);
int Slen = strlen(S);
int Tlen = strlen(T);
mkHash(T,hash,Tlen);
getPos(S,Slen,hash);
system("pause");
return 0;
}
好,看看输出:
就是一个很长的模式串例如“432A5234B5664C3243454”,再给一个目标串“ABC”,只要模式串中某一个字符串同事包含目标串中的每一个元素即可!
要求很低!很明显的用暴力匹配很容易就做出来了,但是暴力匹配算法的时间复杂度很低,是乘方级的(O(n^m))!KMP算法很难处理这种模糊的匹配。
如何才能提高效率呢,利用hash表就很容易解决这个问题,而且是一个相当简单的哈希表,非常有利于新人理解hash表。
由于字符串最多只有255位,所以这个hash表就只有0~255这些元素,根据ASCII表的码值作为hash数组的下标,如果在目标串中存在,相应的位置元素为1,
其余的位置都是0。这样我们可以构建一个数组来统计目标串的字符是否出现在模式串中。
代码时间,首先制作一个hash表,由于在main函数中,我已经将hash表的每一个元素都初始化为0,这样只要将相应位置修改即可:
[plain] view
plaincopyprint?
/*
功能:实现一个比较高级的字符匹配算法,即一串很长的字符,要求找到符合要求字符的字符串
姓名:***
时间:0:10 2014/1/18
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/*制作hash表并初始化*/
void mkHash(char T[],char hash[],int n)
{
if(!T)
{
exit(-1);
}
for (int i = 0 ; i< n ; i++)
{
hash[T[i]] = 1; /*根据ASCII表的码值作为hash数组的下标*/
}
}
下面这个函数就是某个字符是否在hash中出现了
[plain] view
plaincopyprint?
int isExit(char str,char hash[])
{
if(!hash)
{
exit(-1);
}
if(hash[str] == 0)
{
return 0;
}
else
{
return 1;
}
}
接下来这个是就是主要函数了,遍历模式串,主要匹配就输出没有什么难点很容易看得懂:
[plain] view
plaincopyprint?
void getPos(char S[] , int n , char hash[])
{
if(!S && !hash)
{
exit(-1);
}
for (int i=0;i<n;i++)
{
if(hash[S[i]] == 1)
{
printf("%d ",i+1);
hash[S[i]] = 0;
}
}
}
再从main引导:
[plain] view
plaincopyprint?
int main()
{
char S[255];
char T[255];
char hash[255] = {0};
gets(S);
gets(T);
int Slen = strlen(S);
int Tlen = strlen(T);
mkHash(T,hash,Tlen);
getPos(S,Slen,hash);
system("pause");
return 0;
}
好,看看输出:
相关文章推荐
- groovy及gradle dsl文档地址
- JS刷新当前页面的几种方法总结
- ARP欺骗&SSH隧道实验
- Delphi 调试
- Git分支 - 变基
- MarkDown常用语法及示例
- Scanner和BufferReader区别
- Oracle Data Provider for .NET的使用(二)-驱动更换与注意事项
- java中的sleep()和wait()的区别
- 9.18 day second 注意事项
- java-web-j2e学习建议路线
- HTML5 重力感应 JS调试
- php随笔-正则匹配&php浅复制&require跟include
- linux信号机制
- C++ json库jsoncpp 吐槽
- bat 卸载程序的脚本
- 安卓系统一键root:z4root详细使用教程
- 第二周项目3(2)体验复杂度
- LEETCODE-Remove Duplicates from Sorted List
- Win7网络连接正常,但是上不了网