-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathstrstr.c
147 lines (122 loc) · 3.92 KB
/
strstr.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* Joao Paulo Mendes de Sa */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <limits.h>
#ifndef STRSTR_H
#define STRSTR_H
#include "strstr.h"
#endif
/* Check whether memory allocation fails. */
#define CHKMLC(x) \
if ((x) == NULL){ \
fprintf(stderr, "Malloc Failed\n"); \
abort();}
char *strstr_bf(char *haystack, char *needle)
{
int pos, shift;
/* Sanity check. */
if (needle[0] == '\0')
return haystack;
for (shift = 0; haystack[shift] != '\0'; shift++)
for (pos = 0; haystack[pos + shift] == needle[pos]; pos++)
if (needle[pos + 1] == '\0')
return haystack + shift;
return NULL;
}
char *strstr_kmp(char *haystack, char *needle)
{
int *matchTable, pos, cnd, shift;
/* Sanity check. */
if (needle[0] == '\0')
return haystack;
if (haystack[0] == '\0')
return NULL;
CHKMLC(matchTable = malloc(sizeof(int) * strlen(needle)));
/* Build partial match table for string needle. */
pos = 2; /* Current postion of matchTable being computed. */
cnd = 0; /* Last character of prefix candidate for current substring. */
matchTable[0] = -1;
matchTable[1] = 0;
while (needle[pos] != '\0'){
if (needle[pos - 1] == needle[cnd]){ /* Prefix found. */
matchTable[pos] = cnd + 1;
pos++; cnd++;
} else if (cnd > 0) /* Fall back on next candidate. */
cnd = matchTable[cnd];
else { /* No candidates. (cnd = 0)*/
matchTable[pos] = 0;
pos++;
}
}
/* Search for string needle in string haystack. */
pos = 0;
shift = 0;
while (haystack[pos + shift] != '\0' && needle[pos] != '\0'){
if (haystack[pos + shift] == needle[pos])
pos++;
else {
shift += pos - matchTable[pos];
if (pos > 0)
pos = matchTable[pos];
}
}
free(matchTable);
if (needle[pos] == '\0')
return haystack + shift;
else /* needle not found. */
return NULL;
}
char *strstr_bmh(char *haystack, char *needle)
{
int needleLen, haystackLen, bcTable[UCHAR_MAX + 1], i;
needleLen = strlen(needle);
haystackLen = strlen(haystack);
/* Sanity check. */
if (needle[0] == '\0')
return haystack;
/* Initialize bad char shift table and populate with analysis of needle. */
for (i = 0; i < UCHAR_MAX + 1; i++)
bcTable[i] = needleLen;
for (i = 0; i < needleLen - 1; i++)
bcTable[(unsigned char)needle[i]] = needleLen - 1 - i;
while (haystackLen >= needleLen){
/* Match needle to haystack from right to left. */
for (i = needleLen - 1; needle[i] == haystack[i]; i--)
if (i == 0)
return haystack;
/* Shift haystack based on bad char shift table. */
haystackLen -= bcTable[(unsigned char)haystack[needleLen - 1]];
haystack += bcTable[(unsigned char)haystack[needleLen - 1]];
}
/* No match. */
return NULL;
}
char *strstr_bitap(char *haystack, char *needle)
{
unsigned long long bitArr;
unsigned long long needleMask[UCHAR_MAX + 1];
int needleLen = strlen(needle), i;
/* Sanity check. */
if (needle[0] == '\0')
return haystack;
/* Pattern too long. */
if (needleLen > 63)
return strstr_bmh(haystack, needle);
/* Initialize to 1111...0 */
bitArr = ~1;
/* Initialize the needle bitmasks. */
for (i = 0; i < UCHAR_MAX + 1; i++)
needleMask[i] = ~0;
for (i = 0; i < needleLen; ++i)
needleMask[(unsigned char)needle[i]] &= ~(1UL << i);
for (i = 0; haystack[i] != '\0'; i++){
/* Update bit array. */
bitArr |= needleMask[(unsigned char)haystack[i]];
bitArr <<= 1;
/* If 0 reached end of bitArr then needle found. */
if (0 == (bitArr & (1UL << needleLen)))
return haystack + i - needleLen + 1;
}
return NULL;
}