일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- Seg
- 트라이
- SCC
- dinic
- spfa
- 아호코라식
- 월세
- LCA
- 오블완
- 티스토리챌린지
- treedp
- 임대차계약
- 구현
- 접미사배열
- 이분탐색
- Segment tree
- 2SAT
- lcp
- suffix array
- 트리dp
- 좌표압축
- 이분매칭
- 전월세
- 유량
- 세그먼트트리
- 2-sat
- TRIE
- MCMF
- 투룸
- 디닉
Archives
- Today
- Total
N coding
2809_아스키거리 본문
진짜 극혐... 어제부터 계속 붙잡고 있었다.
딱히 붙잡고 있을만큼 영양가 있는 문제는 아니었는데
이게 풀이가 suffix array랑 아호코라식 두개가 있는데 suffix 풀이가 궁금해서 내가 그나마 풀 수 있는 아호코라식으로 열심히 비벼봄..ㅠ
coci에 솔루션은 있는데 정답 코드가 없다.
일단 나는 보자마자 아호코라식이 생각나서 그걸로 접근했다-> 26*4*5000*5000하면 당연히 메모리 터짐
그냥 Trie면 내가 아름다운 이름을 푼 방식이나 그렇게 접근할텐데
아호코라식이라 queue에서 bfs를 돌 때 구하기 좀 빡세서.. 쥬륵
map으로 해봐도 안되고 -> 근데 아름다운 이름에서도 map을 써본 결과 map은 딱히 메모리를 엄청나게 줄여주진 않는 거 같다. 얘는 쓸때마다 터짐
결국 질문검색에서 찾다가 vector + bitmask를 쓰신 분이 있길래 한 번 해보기나 하자 하고 짜봤다.
극혐~메모리 최적화~극혐
+)
https://www.acmicpc.net/source/6463084
suffix array 코드를 찾다가 다른 코드는 이해불가능인데 친절하게 설명을 써놓으셨고 코드도 가독성 좋게 잘 짜셔서 이해할 수 있었다..!
이게 sa 정해인 것 같다 갓..갓..
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 148 149 150 | #include <iostream> #include <string.h> #include <string> #include <queue> #include <vector> #include <algorithm> #include <map> using namespace std; #define MAX 100001 int N, M; int mark[300001], chk[300001]; string str2; char str[300002]; //1. n번째가 어떤 문자인지 //2. 현재 문자가 존재하는지 //3. 어떤 문자가 몇번째에 존재하는지 int isexist(int& exist, int ch) { //현재 문자가 존재하는지 return (exist & (1 << (25-ch))); } int whatch(int& exist, int ch) { //ch가 몇번째에 존재하는지 int cnt = 0; for (int i = 0; i < ch; ++i) { if (exist & (1 << (25 - i))) cnt++; } return cnt; } int nthch(int& exist, int n) { //n번째 문자가 뭐인지 int cnt = 0; for (int i = 0; i < 26; ++i) { if (exist & (1 << (25 - i))) { if (cnt == n) return i; cnt++; } } return -1; } struct Trie { vector<Trie*> next; Trie* fail; int output; int exist; Trie() { fail = nullptr; output = exist = 0; } ~Trie() { for (int i = 0; i < next.size(); ++i) { delete next[i]; } } void insert(const char* key, int len) { if (*key == '\0') { if (output < len) { output = len; } } else { int cur = *key - 'a'; int n = whatch(exist, cur); if (!isexist(exist, cur)) { exist |= (1 << (25 - cur)); next.insert(next.begin() + n, new Trie()); } next[n]->insert(key + 1, len); } } }; int main() { cin.tie(NULL); cout.tie(NULL); ios::sync_with_stdio(false); //freopen("poplocavanje.in.3", "r", stdin); Trie* root = new Trie(); cin >> N; cin >> str; cin >> M; for (int i = 0; i < M; ++i) { cin >> str2; if (str2.length() > N) continue; root->insert(&str2[0], str2.length()); } queue<Trie*> q; root->fail = root; q.push(root); while (!q.empty()) { Trie* curr = q.front(); q.pop(); for (int i = 0; i < curr->next.size(); ++i) { Trie* next = curr->next[i]; if (curr == root) next->fail = root; else { int nthCh = nthch(curr->exist, i); //curr에서 i번째가 어떤 문자인지 Trie* desc = curr->fail; //desc에 nthCh가 있을 때까지 while (desc != root && !isexist(desc->exist, nthCh)) desc = desc->fail; //desc에 nthCh가 존재하는 경우 //desc의 배열에 몇번째에 nthCh가 존재하는지 if (isexist(desc->exist, nthCh)) desc = desc->next[whatch(desc->exist, nthCh)]; next->fail = desc; } if (next->fail->output) { if (next->output < next->fail->output) { next->output = next->fail->output; } } q.push(next); } } Trie* curr = root; for (int c = 0; str[c]; ++c) { int next = str[c] - 'a'; while (curr != root && !isexist(curr->exist, next)) curr = curr->fail; if (isexist(curr->exist, next)) curr = curr->next[whatch(curr->exist, next)]; if (curr->output) { mark[c] = max(mark[c], curr->output); } } int res = 0; for (int i = N - 1; i >= 0; --i) { int check = mark[i]; if (check == 0 && chk[i] == 0) res++; while (chk[i - check + 1] == 0 && i - check + 1 <= i) { chk[i - check + 1] = 1; check--; } } cout << res; delete root; } | cs |
'PS' 카테고리의 다른 글
1886_프리즌 브레이크/Evacuation (0) | 2018.09.06 |
---|---|
13576_Prefix와 Suffix (0) | 2018.08.31 |
4217_신성문자 (0) | 2018.08.30 |
15940_네트워크 연결 (2) | 2018.08.29 |
3654_L퍼즐 (0) | 2018.08.29 |