fork download
  1.  
  2. import java.io.BufferedReader;
  3. import java.io.IOException;
  4. import java.io.InputStreamReader;
  5. import java.io.StreamTokenizer;
  6. import java.util.ArrayList;
  7. import java.util.Arrays;
  8. import java.util.EnumSet;
  9. import javax.print.attribute.standard.Sides;
  10.  
  11. public class strings_kp2 {
  12.  
  13. static int[] tableLong;
  14. static int[] tableShort1;
  15. static int[] tableShort2;
  16.  
  17. static int[] createTable(int[] w) {
  18. int[] table = new int[w.length];
  19. int pos = 2;
  20. int cnd = 0;
  21.  
  22. table[0] = -1;
  23. while (pos < w.length) {
  24. if (w[pos - 1] == w[cnd]) {
  25. cnd++;
  26. table[pos] = cnd;
  27. pos++;
  28.  
  29. } else if (cnd > 0) {
  30. cnd = table[cnd];
  31. } else {
  32. table[pos] = 0;
  33. pos++;
  34. }
  35. }
  36. return table;
  37. }
  38.  
  39. private static int kmp(int[] w, int[] s, int[] table) {
  40.  
  41. int m = 0;
  42. int i = 0;
  43.  
  44. while (m + i < s.length) {
  45. if (w[i] == s[m + i]) {
  46. if (i == w.length - 1) {
  47. return m;
  48. }
  49. i++;
  50. } else {
  51. m = m + i - table[i];
  52. if (table[i] > -1) {
  53. i = table[i];
  54. } else {
  55. i = 0;
  56. }
  57. }
  58.  
  59. }
  60. return s.length;
  61. }
  62.  
  63. static enum Side {
  64.  
  65. T {
  66.  
  67. Side opposite() {
  68. return Side.B;
  69. }
  70.  
  71. Side flip() {
  72. return Side.L;
  73. }
  74. }, L {
  75.  
  76. Side opposite() {
  77. return Side.R;
  78. }
  79.  
  80. Side flip() {
  81. return Side.T;
  82. }
  83. }, R {
  84.  
  85. Side opposite() {
  86. return Side.L;
  87. }
  88.  
  89. Side flip() {
  90. return Side.B;
  91. }
  92. }, B {
  93.  
  94. Side opposite() {
  95. return Side.T;
  96. }
  97.  
  98. Side flip() {
  99. return Side.R;
  100. }
  101. };
  102. Line[] lines;
  103.  
  104. abstract Side opposite();
  105.  
  106. abstract Side flip();
  107. }
  108.  
  109. static int nextInt() {
  110. try {
  111. st.nextToken();
  112. return (int) st.nval;
  113. } catch (IOException ex) {
  114. return 0;
  115. }
  116. }
  117.  
  118. static Side nextSide() {
  119. try {
  120. st.nextToken();
  121. switch (st.sval.charAt(0)) {
  122. case 'T':
  123. return Side.T;
  124. case 'L':
  125. return Side.L;
  126. case 'R':
  127. return Side.R;
  128. default:
  129. return Side.B;
  130. }
  131. } catch (IOException ex) {
  132. return Side.T;
  133. }
  134. }
  135.  
  136. static enum Type {
  137.  
  138. TL, TR, TB, LR, LB, RB;
  139. int count;
  140. }
  141.  
  142. static int getType(int start, int end) {
  143. switch (start) {
  144. case 0:
  145. switch (end) {
  146. case 1:
  147. return 0;
  148. case 2:
  149. return 1;
  150. default:
  151. return 2;
  152. }
  153. case 1:
  154. switch (end) {
  155. case 2:
  156. return 3;
  157. default:
  158. return 4;
  159. }
  160. default:
  161. return 5;
  162. }
  163. }
  164.  
  165. static final class Line {
  166.  
  167. Side s1, s2;
  168. int a, b;
  169. Type type;
  170. boolean used;
  171.  
  172. private Line(Side s1, Side s2, int a, int b) {
  173. if (s1.ordinal() > s2.ordinal()) {
  174. Side t = s1;
  175. s1 = s2;
  176. s2 = t;
  177. int ti = a;
  178. a = b;
  179. b = ti;
  180. }
  181. this.s1 = s1;
  182. this.s2 = s2;
  183. this.a = a;
  184. this.b = b;
  185. s1.lines[a] = this;
  186. s2.lines[b] = this;
  187. setType();
  188. }
  189.  
  190. public String toString() {
  191. return "(" + s1 + ":" + a + "," + s2 + ":" + b + ")";
  192. }
  193.  
  194. void setType() {
  195. switch (s1) {
  196. case T:
  197. switch (s2) {
  198. case R:
  199. type = Type.TR;
  200. break;
  201. case L:
  202. type = Type.TL;
  203. break;
  204. default:
  205. type = Type.TB;
  206. }
  207. break;
  208. case L:
  209. switch (s2) {
  210. case R:
  211. type = Type.LR;
  212. break;
  213. default:
  214. type = Type.LB;
  215. }
  216. break;
  217. default:
  218. type = Type.RB;
  219. }
  220. }
  221. }
  222. static int n, m;
  223. static boolean flip;
  224. static int shortCount;
  225. static ArrayList<Integer> theCycle = new ArrayList<Integer>();
  226. static ArrayList<ArrayList<Integer>> allCycles = new ArrayList<ArrayList<Integer>>();
  227. static ArrayList<Integer> cyclePoints = new ArrayList<Integer>();
  228. static ArrayList<ArrayList<Integer>> allPoints = new ArrayList<ArrayList<Integer>>();
  229. static ArrayList<Integer> cycleSides = new ArrayList<Integer>();
  230. static ArrayList<Integer> rotations = new ArrayList<Integer>();
  231.  
  232. static boolean findSolution() {
  233. if (Type.LR.count > 0) {
  234. return false;
  235. }
  236. if (Type.TR.count != Type.LB.count) {
  237. return false;
  238. }
  239. if (Type.TL.count != Type.RB.count) {
  240. return false;
  241. }
  242. if (Type.TB.count != m - (Type.TL.count + Type.TR.count)) {
  243. return false;
  244. }
  245. shortCount = Math.min(Type.TL.count, Type.TR.count);
  246.  
  247. int topSize = m - (shortCount * 2);
  248. int sideSize = n - (shortCount * 2);
  249.  
  250. if (Type.TL.count == Type.TR.count) {
  251. theCycle.add(Type.TB.ordinal());
  252. cyclePoints.add(shortCount);
  253. cycleSides.add(0);
  254. allCycles.add(theCycle);
  255. allPoints.add(cyclePoints);
  256. for (int i = shortCount + 1; i < shortCount + topSize; i++) {
  257. ArrayList<Integer> newCycle = new ArrayList<Integer>();
  258. ArrayList<Integer> newPoints = new ArrayList<Integer>();
  259. newCycle.add(Type.TB.ordinal());
  260. newPoints.add(i);
  261. allCycles.add(newCycle);
  262. allPoints.add(newPoints);
  263. }
  264. return true;
  265. }
  266. boolean right = Type.TL.count < Type.TR.count;
  267.  
  268. int l = Side.L.ordinal();
  269. int r = Side.R.ordinal();
  270. int t = Side.T.ordinal();
  271. int b = Side.B.ordinal();
  272. int[][] nextSides = new int[4][m];
  273. int[][] nextPoints = new int[4][m];
  274. if (right) {
  275. for (int i = 0; i < sideSize; i++) {
  276. nextSides[l][shortCount + i] = b;
  277. nextPoints[l][shortCount + i] = shortCount + sideSize - i - 1;
  278. nextSides[b][shortCount + sideSize - i - 1] = l;
  279. nextPoints[b][shortCount + sideSize - i - 1] = shortCount + i;
  280.  
  281. nextSides[r][shortCount + i] = t;
  282. nextPoints[r][shortCount + i] = m - shortCount - i - 1;
  283. nextSides[t][m - shortCount - i - 1] = r;
  284. nextPoints[t][m - shortCount - i - 1] = shortCount + i;
  285. }
  286.  
  287. for (int i = 0; i < topSize - sideSize; i++) {
  288. nextSides[t][shortCount + i] = b;
  289. nextPoints[t][shortCount + i] = shortCount + sideSize + i;
  290. nextSides[b][shortCount + sideSize + i] = t;
  291. nextPoints[b][shortCount + sideSize + i] = shortCount + i;
  292. }
  293. } else {
  294. for (int i = 0; i < sideSize; i++) {
  295. nextSides[l][shortCount + i] = t;
  296. nextPoints[l][shortCount + i] = shortCount + i;
  297. nextSides[t][shortCount + i] = l;
  298. nextPoints[t][shortCount + i] = shortCount + i;
  299.  
  300. nextSides[r][shortCount + i] = b;
  301. nextPoints[r][shortCount + i] = m - shortCount - sideSize + i;
  302. nextSides[b][m - shortCount - sideSize + i] = r;
  303. nextPoints[b][m - shortCount - sideSize + i] = shortCount + i;
  304. }
  305.  
  306. for (int i = 0; i < topSize - sideSize; i++) {
  307. nextSides[b][shortCount + i] = t;
  308. nextPoints[b][shortCount + i] = shortCount + sideSize + i;
  309. nextSides[t][shortCount + sideSize + i] = b;
  310. nextPoints[t][shortCount + sideSize + i] = shortCount + i;
  311. }
  312. }
  313. boolean[][] used = new boolean[4][m];
  314. int curSide = t;
  315. int curPos = shortCount;
  316. while (!used[curSide][curPos]) {
  317. used[curSide][curPos] = true;
  318. int nextSide = nextSides[curSide][curPos];
  319. int nextPos = nextPoints[curSide][curPos];
  320. theCycle.add(getType(curSide, nextSide));
  321. cyclePoints.add(curPos);
  322. cycleSides.add(curSide % 3 == 0 ? 0 : 1);
  323. curSide = 3 - nextSide;
  324. curPos = nextPos;
  325. }
  326. allCycles.add(theCycle);
  327. allPoints.add(cyclePoints);
  328. for (int i = shortCount; i < shortCount + topSize; i++) {
  329. if (!used[0][i]) {
  330. ArrayList<Integer> newCycle = new ArrayList<Integer>();
  331. ArrayList<Integer> newPoints = new ArrayList<Integer>();
  332. curSide = t;
  333. curPos = i;
  334. while (!used[curSide][curPos]) {
  335. used[curSide][curPos] = true;
  336. int nextSide = nextSides[curSide][curPos];
  337. int nextPos = nextPoints[curSide][curPos];
  338. newCycle.add(getType(curSide, nextSide));
  339. newPoints.add(curPos);
  340. curSide = 3 - nextSide;
  341. curPos = nextPos;
  342. }
  343. allCycles.add(newCycle);
  344. allPoints.add(newPoints);
  345. }
  346. }
  347.  
  348.  
  349. return true;
  350. }
  351.  
  352. public static void main(String[] args) {
  353. n = nextInt();
  354. m = nextInt();
  355.  
  356. if (n > m) {
  357. flip = true;
  358. int t = n;
  359. n = m;
  360. m = t;
  361. }
  362.  
  363. Side.T.lines = new Line[m];
  364. Side.B.lines = new Line[m];
  365. Side.L.lines = new Line[n];
  366. Side.R.lines = new Line[n];
  367.  
  368.  
  369. ArrayList<Line> lines = new ArrayList<Line>();
  370.  
  371. for (int i = 0; i < n + m; i++) {
  372. Side s1 = nextSide();
  373. Side s2 = nextSide();
  374. if (flip) {
  375. s1 = s1.flip();
  376. s2 = s2.flip();
  377. }
  378. lines.add(new Line(s1, s2, nextInt() - 1, nextInt() - 1));
  379. }
  380. for (Line l : lines) {
  381. l.type.count++;
  382. }
  383.  
  384. if (!findSolution()) {
  385. System.out.println("No solution");
  386. return;
  387. }
  388. int[] longCycle = new int[theCycle.size()];
  389. for (int i = 0; i < theCycle.size(); i++) {
  390. longCycle[i] = theCycle.get(i);
  391. }
  392.  
  393.  
  394. int[] shortCycle1 = {0, 4, 5, 1};
  395. int[] shortCycle2 = {0, 1, 5, 4};
  396.  
  397. tableLong = createTable(longCycle);
  398. tableShort1 = createTable(shortCycle1);
  399. tableShort2 = createTable(shortCycle2);
  400. rotations.add(0);
  401. for (int i = 1; i < allCycles.size(); i++) {
  402. int length = theCycle.size();
  403. int[] curCycle = new int[length * 2];
  404. for (int j = 0; j < length; j++) {
  405. curCycle[j] = allCycles.get(i).get(j);
  406. }
  407. for (int j = 0; j < length; j++) {
  408. curCycle[j + length] = allCycles.get(i).get(j);
  409. }
  410. rotations.add(kmp(longCycle, curCycle, tableLong));
  411. }
  412.  
  413. ArrayList<ArrayList<Line>> cycles = new ArrayList<ArrayList<Line>>();
  414.  
  415. for (Line l : lines) {
  416. if (!l.used) {
  417. ArrayList<Line> cycle = new ArrayList<Line>();
  418. Line next = l;
  419. while (!next.used) {
  420. cycle.add(next);
  421. next.used = true;
  422. if (!next.s2.opposite().lines[next.b].used) {
  423. next = next.s2.opposite().lines[next.b];
  424. } else if (!next.s1.opposite().lines[next.a].used) {
  425. next = next.s1.opposite().lines[next.a];
  426. }
  427. }
  428. cycles.add(cycle);
  429. }
  430. }
  431.  
  432. int actualShortCount = 0;
  433. int longCount = 0;
  434.  
  435. int[] rows = new int[n];
  436. int[] cols = new int[m];
  437.  
  438. for (ArrayList<Line> cycle : cycles) {
  439. int length = cycle.size();
  440.  
  441.  
  442. int[] curCycle = new int[length * 2];
  443. for (int i = 0; i < length; i++) {
  444. curCycle[i] = cycle.get(i).type.ordinal();
  445. }
  446. for (int i = 0; i < length; i++) {
  447. curCycle[length + i] = cycle.get(i).type.ordinal();
  448. }
  449.  
  450. if (length == 4) {
  451. int rot1 = kmp(shortCycle1, curCycle, tableShort1);
  452. int rot2 = kmp(shortCycle2, curCycle, tableShort2);
  453. if (rot1 != 8 || rot2 != 8) {
  454. for (Line l : cycle) {
  455. if (l.type == Type.TL) {
  456. rows[actualShortCount] = l.b;
  457. cols[actualShortCount] = l.a;
  458. } else if (l.type == Type.RB) {
  459. rows[n - 1 - actualShortCount] = l.a;
  460. cols[m - 1 - actualShortCount] = l.b;
  461. }
  462. }
  463. actualShortCount++;
  464. continue;
  465. }
  466. }
  467. if (length != longCycle.length) {
  468. System.out.println("No solution");
  469. return;
  470. }
  471.  
  472. int rot = kmp(longCycle, curCycle, tableLong);
  473. if (rot == 2 * length) {
  474. System.out.println("No solution");
  475. return;
  476. }
  477. for (int i = 0; i < length; i++) {
  478. int pos = allPoints.get(longCount).get((i + rotations.get(longCount)) % length);
  479. int value = cycle.get((rot + i) % length).a;
  480. if (cycleSides.get(i) == 0) {
  481. cols[pos] = value;
  482. } else {
  483. rows[pos] = value;
  484. }
  485. }
  486. longCount++;
  487.  
  488. }
  489.  
  490. if (flip) {
  491. int[] t = rows;
  492. rows = cols;
  493. cols = t;
  494. }
  495.  
  496. for (int i = 0; i < rows.length; i++) {
  497. System.out.print((rows[i] + 1) + " ");
  498. }
  499. System.out.println();
  500. for (int i = 0; i < cols.length; i++) {
  501. System.out.print((cols[i] + 1) + " ");
  502. }
  503. System.out.println();
  504. }
  505. }
  506.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty